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

codeigniter4 / CodeIgniter4 / 23692808335

28 Mar 2026 07:38PM UTC coverage: 86.555%. First build
23692808335

Pull #10070

github

web-flow
Merge 3c1fd9bf9 into 34833344f
Pull Request #10070: feat: add support to parse the `--` separator for commands

32 of 34 new or added lines in 3 files covered. (94.12%)

22692 of 26217 relevant lines covered (86.55%)

219.96 hits per line

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

62.96
/system/HTTP/CLIRequest.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\HTTP;
15

16
use CodeIgniter\CLI\CommandLineParser;
17
use CodeIgniter\Exceptions\RuntimeException;
18
use Config\App;
19
use Locale;
20

21
/**
22
 * Represents a request from the command-line. Provides additional
23
 * tools to interact with that request since CLI requests are not
24
 * static like HTTP requests might be.
25
 *
26
 * Portions of this code were initially from the FuelPHP Framework,
27
 * version 1.7.x, and used here under the MIT license they were
28
 * originally made available under.
29
 *
30
 * http://fuelphp.com
31
 *
32
 * @see \CodeIgniter\HTTP\CLIRequestTest
33
 */
34
class CLIRequest extends Request
35
{
36
    /**
37
     * Stores the segments of our cli "URI" command.
38
     *
39
     * @var array
40
     */
41
    protected $segments = [];
42

43
    /**
44
     * Command line options and their values.
45
     *
46
     * @var array
47
     */
48
    protected $options = [];
49

50
    /**
51
     * Command line arguments (segments and options).
52
     *
53
     * @var array
54
     */
55
    protected $args = [];
56

57
    /**
58
     * Set the expected HTTP verb
59
     *
60
     * @var string
61
     */
62
    protected $method = 'CLI';
63

64
    /**
65
     * Constructor
66
     */
67
    public function __construct(App $config)
68
    {
69
        if (! is_cli()) {
77✔
70
            throw new RuntimeException(static::class . ' needs to run from the command line.'); // @codeCoverageIgnore
×
71
        }
72

73
        parent::__construct($config);
77✔
74

75
        // Don't terminate the script when the cli's tty goes away
76
        ignore_user_abort(true);
77✔
77

78
        $parser = new CommandLineParser($this->getServer('argv') ?? []);
77✔
79

80
        $this->segments = $parser->getArguments();
77✔
81
        $this->options  = $parser->getOptions();
77✔
82
        $this->args     = $parser->getTokens();
77✔
83

84
        // Set SiteURI for this request
85
        $this->uri = new SiteURI($config, $this->getPath());
77✔
86
    }
87

88
    /**
89
     * Returns the "path" of the request script so that it can be used
90
     * in routing to the appropriate controller/method.
91
     *
92
     * The path is determined by treating the command line arguments
93
     * as if it were a URL - up until we hit our first option.
94
     *
95
     * Example:
96
     *      php index.php users 21 profile -foo bar
97
     *
98
     *      // Routes to /users/21/profile (index is removed for routing sake)
99
     *      // with the option foo = bar.
100
     */
101
    public function getPath(): string
102
    {
103
        return implode('/', $this->segments);
77✔
104
    }
105

106
    /**
107
     * Returns an associative array of all CLI options found, with
108
     * their values.
109
     */
110
    public function getOptions(): array
111
    {
112
        return $this->options;
1✔
113
    }
114

115
    /**
116
     * Returns an array of all CLI arguments (segments and options).
117
     */
118
    public function getArgs(): array
119
    {
120
        return $this->args;
1✔
121
    }
122

123
    /**
124
     * Returns the path segments.
125
     */
126
    public function getSegments(): array
127
    {
128
        return $this->segments;
2✔
129
    }
130

131
    /**
132
     * Returns the value for a single CLI option that was passed in.
133
     *
134
     * @return string|null
135
     */
136
    public function getOption(string $key)
137
    {
138
        return $this->options[$key] ?? null;
1✔
139
    }
140

141
    /**
142
     * Returns the options as a string, suitable for passing along on
143
     * the CLI to other commands.
144
     *
145
     * Example:
146
     *      $options = [
147
     *          'foo' => 'bar',
148
     *          'baz' => 'queue some stuff'
149
     *      ];
150
     *
151
     *      getOptionString() = '-foo bar -baz "queue some stuff"'
152
     */
153
    public function getOptionString(bool $useLongOpts = false): string
154
    {
155
        if ($this->options === []) {
5✔
156
            return '';
1✔
157
        }
158

159
        $out = '';
4✔
160

161
        foreach ($this->options as $name => $value) {
4✔
162
            if ($useLongOpts && mb_strlen($name) > 1) {
4✔
163
                $out .= "--{$name} ";
4✔
164
            } else {
165
                $out .= "-{$name} ";
4✔
166
            }
167

168
            if ($value === null) {
4✔
169
                continue;
×
170
            }
171

172
            if (mb_strpos($value, ' ') !== false) {
4✔
173
                $out .= '"' . $value . '" ';
4✔
174
            } else {
175
                $out .= "{$value} ";
4✔
176
            }
177
        }
178

179
        return trim($out);
4✔
180
    }
181

182
    /**
183
     * Parses the command line it was called from and collects all options
184
     * and valid segments.
185
     *
186
     * NOTE: I tried to use getopt but had it fail occasionally to find
187
     * any options, where argv has always had our back.
188
     *
189
     * @deprecated 4.8.0 No longer used.
190
     *
191
     * @return void
192
     */
193
    protected function parseCommand()
194
    {
NEW
195
        @trigger_error(sprintf('The %s() method is deprecated and no longer used.', __METHOD__), E_USER_DEPRECATED);
×
196

197
        $args = $this->getServer('argv');
×
198
        array_shift($args); // Scrap index.php
×
199

200
        $optionValue = false;
×
201

202
        foreach ($args as $i => $arg) {
×
203
            if (mb_strpos($arg, '-') !== 0) {
×
204
                if ($optionValue) {
×
205
                    $optionValue = false;
×
206
                } else {
207
                    $this->segments[] = $arg;
×
208
                    $this->args[]     = $arg;
×
209
                }
210

211
                continue;
×
212
            }
213

214
            $arg   = ltrim($arg, '-');
×
215
            $value = null;
×
216

217
            if (isset($args[$i + 1]) && mb_strpos($args[$i + 1], '-') !== 0) {
×
218
                $value       = $args[$i + 1];
×
219
                $optionValue = true;
×
220
            }
221

222
            $this->options[$arg] = $value;
×
223
            $this->args[$arg]    = $value;
×
224
        }
225
    }
226

227
    /**
228
     * Determines if this request was made from the command line (CLI).
229
     */
230
    public function isCLI(): bool
231
    {
232
        return true;
1✔
233
    }
234

235
    /**
236
     * Fetch an item from GET data.
237
     *
238
     * @param array|string|null $index  Index for item to fetch from $_GET.
239
     * @param int|null          $filter A filter name to apply.
240
     * @param array|int|null    $flags
241
     *
242
     * @return array|null
243
     */
244
    public function getGet($index = null, $filter = null, $flags = null)
245
    {
246
        return $this->returnNullOrEmptyArray($index);
1✔
247
    }
248

249
    /**
250
     * Fetch an item from POST.
251
     *
252
     * @param array|string|null $index  Index for item to fetch from $_POST.
253
     * @param int|null          $filter A filter name to apply
254
     * @param array|int|null    $flags
255
     *
256
     * @return array|null
257
     */
258
    public function getPost($index = null, $filter = null, $flags = null)
259
    {
260
        return $this->returnNullOrEmptyArray($index);
1✔
261
    }
262

263
    /**
264
     * Fetch an item from POST data with fallback to GET.
265
     *
266
     * @param array|string|null $index  Index for item to fetch from $_POST or $_GET
267
     * @param int|null          $filter A filter name to apply
268
     * @param array|int|null    $flags
269
     *
270
     * @return array|null
271
     */
272
    public function getPostGet($index = null, $filter = null, $flags = null)
273
    {
274
        return $this->returnNullOrEmptyArray($index);
1✔
275
    }
276

277
    /**
278
     * Fetch an item from GET data with fallback to POST.
279
     *
280
     * @param array|string|null $index  Index for item to be fetched from $_GET or $_POST
281
     * @param int|null          $filter A filter name to apply
282
     * @param array|int|null    $flags
283
     *
284
     * @return array|null
285
     */
286
    public function getGetPost($index = null, $filter = null, $flags = null)
287
    {
288
        return $this->returnNullOrEmptyArray($index);
1✔
289
    }
290

291
    /**
292
     * This is a place holder for calls from cookie_helper get_cookie().
293
     *
294
     * @param array|string|null $index  Index for item to be fetched from $_COOKIE
295
     * @param int|null          $filter A filter name to be applied
296
     * @param mixed             $flags
297
     *
298
     * @return array|null
299
     */
300
    public function getCookie($index = null, $filter = null, $flags = null)
301
    {
302
        return $this->returnNullOrEmptyArray($index);
1✔
303
    }
304

305
    /**
306
     * @param array|string|null $index
307
     *
308
     * @return array|null
309
     */
310
    private function returnNullOrEmptyArray($index)
311
    {
312
        return ($index === null || is_array($index)) ? [] : null;
5✔
313
    }
314

315
    /**
316
     * Gets the current locale, with a fallback to the default
317
     * locale if none is set.
318
     */
319
    public function getLocale(): string
320
    {
321
        return Locale::getDefault();
1✔
322
    }
323

324
    /**
325
     * Checks this request type.
326
     */
327
    public function is(string $type): bool
328
    {
329
        return false;
1✔
330
    }
331
}
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