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

codeigniter4 / CodeIgniter4 / 12739860967

13 Jan 2025 03:03AM UTC coverage: 84.454%. Remained the same
12739860967

push

github

web-flow
chore: add more trailing commas in more places (#9395)

* Apply to parameters

* Apply to array destructuring

* Apply to match

* Apply for arguments

337 of 397 new or added lines in 117 files covered. (84.89%)

1 existing line in 1 file now uncovered.

20464 of 24231 relevant lines covered (84.45%)

189.67 hits per line

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

87.72
/system/Commands/Encryption/GenerateKey.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\Commands\Encryption;
15

16
use CodeIgniter\CLI\BaseCommand;
17
use CodeIgniter\CLI\CLI;
18
use CodeIgniter\Config\DotEnv;
19
use CodeIgniter\Encryption\Encryption;
20

21
/**
22
 * Generates a new encryption key.
23
 */
24
class GenerateKey extends BaseCommand
25
{
26
    /**
27
     * The Command's group.
28
     *
29
     * @var string
30
     */
31
    protected $group = 'Encryption';
32

33
    /**
34
     * The Command's name.
35
     *
36
     * @var string
37
     */
38
    protected $name = 'key:generate';
39

40
    /**
41
     * The Command's usage.
42
     *
43
     * @var string
44
     */
45
    protected $usage = 'key:generate [options]';
46

47
    /**
48
     * The Command's short description.
49
     *
50
     * @var string
51
     */
52
    protected $description = 'Generates a new encryption key and writes it in an `.env` file.';
53

54
    /**
55
     * The command's options
56
     *
57
     * @var array<string, string>
58
     */
59
    protected $options = [
60
        '--force'  => 'Force overwrite existing key in `.env` file.',
61
        '--length' => 'The length of the random string that should be returned in bytes. Defaults to 32.',
62
        '--prefix' => 'Prefix to prepend to encoded key (either hex2bin or base64). Defaults to hex2bin.',
63
        '--show'   => 'Shows the generated key in the terminal instead of storing in the `.env` file.',
64
    ];
65

66
    /**
67
     * Actually execute the command.
68
     */
69
    public function run(array $params)
70
    {
71
        $prefix = $params['prefix'] ?? CLI::getOption('prefix');
6✔
72

73
        if (in_array($prefix, [null, true], true)) {
6✔
74
            $prefix = 'hex2bin';
6✔
75
        } elseif (! in_array($prefix, ['hex2bin', 'base64'], true)) {
3✔
76
            $prefix = CLI::prompt('Please provide a valid prefix to use.', ['hex2bin', 'base64'], 'required'); // @codeCoverageIgnore
×
77
        }
78

79
        $length = $params['length'] ?? CLI::getOption('length');
6✔
80

81
        if (in_array($length, [null, true], true)) {
6✔
82
            $length = 32;
6✔
83
        }
84

85
        $encodedKey = $this->generateRandomKey($prefix, $length);
6✔
86

87
        if (array_key_exists('show', $params) || (bool) CLI::getOption('show')) {
6✔
88
            CLI::write($encodedKey, 'yellow');
1✔
89
            CLI::newLine();
1✔
90

91
            return;
1✔
92
        }
93

94
        if (! $this->setNewEncryptionKey($encodedKey, $params)) {
5✔
95
            CLI::write('Error in setting new encryption key to .env file.', 'light_gray', 'red');
1✔
96
            CLI::newLine();
1✔
97

98
            return;
1✔
99
        }
100

101
        // force DotEnv to reload the new env vars
102
        putenv('encryption.key');
4✔
103
        unset($_ENV['encryption.key'], $_SERVER['encryption.key']);
4✔
104
        $dotenv = new DotEnv(ROOTPATH);
4✔
105
        $dotenv->load();
4✔
106

107
        CLI::write('Application\'s new encryption key was successfully set.', 'green');
4✔
108
        CLI::newLine();
4✔
109
    }
110

111
    /**
112
     * Generates a key and encodes it.
113
     */
114
    protected function generateRandomKey(string $prefix, int $length): string
115
    {
116
        $key = Encryption::createKey($length);
6✔
117

118
        if ($prefix === 'hex2bin') {
6✔
119
            return 'hex2bin:' . bin2hex($key);
6✔
120
        }
121

122
        return 'base64:' . base64_encode($key);
3✔
123
    }
124

125
    /**
126
     * Sets the new encryption key in your .env file.
127
     *
128
     * @param array<int|string, string|null> $params
129
     */
130
    protected function setNewEncryptionKey(string $key, array $params): bool
131
    {
132
        $currentKey = env('encryption.key', '');
5✔
133

134
        if ($currentKey !== '' && ! $this->confirmOverwrite($params)) {
5✔
135
            // Not yet testable since it requires keyboard input
136
            return false; // @codeCoverageIgnore
×
137
        }
138

139
        return $this->writeNewEncryptionKeyToFile($currentKey, $key);
5✔
140
    }
141

142
    /**
143
     * Checks whether to overwrite existing encryption key.
144
     *
145
     * @param array<int|string, string|null> $params
146
     */
147
    protected function confirmOverwrite(array $params): bool
148
    {
149
        return (array_key_exists('force', $params) || CLI::getOption('force')) || CLI::prompt('Overwrite existing key?', ['n', 'y']) === 'y';
3✔
150
    }
151

152
    /**
153
     * Writes the new encryption key to .env file.
154
     */
155
    protected function writeNewEncryptionKeyToFile(string $oldKey, string $newKey): bool
156
    {
157
        $baseEnv = ROOTPATH . 'env';
5✔
158
        $envFile = ROOTPATH . '.env';
5✔
159

160
        if (! is_file($envFile)) {
5✔
161
            if (! is_file($baseEnv)) {
4✔
162
                CLI::write('Both default shipped `env` file and custom `.env` are missing.', 'yellow');
1✔
163
                CLI::write('Here\'s your new key instead: ' . CLI::color($newKey, 'yellow'));
1✔
164
                CLI::newLine();
1✔
165

166
                return false;
1✔
167
            }
168

169
            copy($baseEnv, $envFile);
3✔
170
        }
171

172
        $oldFileContents = (string) file_get_contents($envFile);
4✔
173
        $replacementKey  = "\nencryption.key = {$newKey}";
4✔
174

175
        if (! str_contains($oldFileContents, 'encryption.key')) {
4✔
176
            return file_put_contents($envFile, $replacementKey, FILE_APPEND) !== false;
1✔
177
        }
178

179
        $newFileContents = preg_replace($this->keyPattern($oldKey), $replacementKey, $oldFileContents);
3✔
180

181
        if ($newFileContents === $oldFileContents) {
3✔
182
            $newFileContents = preg_replace(
×
183
                '/^[#\s]*encryption.key[=\s]*(?:hex2bin\:[a-f0-9]{64}|base64\:(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?)$/m',
×
184
                $replacementKey,
×
NEW
185
                $oldFileContents,
×
186
            );
×
187
        }
188

189
        return file_put_contents($envFile, $newFileContents) !== false;
3✔
190
    }
191

192
    /**
193
     * Get the regex of the current encryption key.
194
     */
195
    protected function keyPattern(string $oldKey): string
196
    {
197
        $escaped = preg_quote($oldKey, '/');
3✔
198

199
        if ($escaped !== '') {
3✔
200
            $escaped = "[{$escaped}]*";
3✔
201
        }
202

203
        return "/^[#\\s]*encryption.key[=\\s]*{$escaped}$/m";
3✔
204
    }
205
}
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

© 2025 Coveralls, Inc