Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
20 | class OpenSSL extends Abstraction implements Executable |
||
21 | { |
||
22 | use OptionMasker; |
||
23 | |||
24 | /** |
||
25 | * Encryption modes |
||
26 | */ |
||
27 | const MODE_CERT = 'smime'; |
||
28 | const MODE_PASS = 'enc'; |
||
29 | |||
30 | /** |
||
31 | * Use password or key |
||
32 | * |
||
33 | * @var string |
||
34 | */ |
||
35 | private $mode; |
||
36 | |||
37 | /** |
||
38 | * File to encrypt |
||
39 | * |
||
40 | * @var string |
||
41 | */ |
||
42 | private $sourceFile; |
||
43 | |||
44 | /** |
||
45 | * SSL Cert file |
||
46 | * |
||
47 | * @var string |
||
48 | */ |
||
49 | private $certFile; |
||
50 | |||
51 | /** |
||
52 | * Password |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | private $password; |
||
57 | |||
58 | /** |
||
59 | * Algorithm to use |
||
60 | * |
||
61 | * @var string |
||
62 | */ |
||
63 | private $algorithm; |
||
64 | |||
65 | /** |
||
66 | * Use base64 encoding |
||
67 | * |
||
68 | * @var boolean |
||
69 | */ |
||
70 | private $base64; |
||
71 | |||
72 | /** |
||
73 | * Path to the encrypted file |
||
74 | * |
||
75 | * @var string |
||
76 | */ |
||
77 | private $targetFile; |
||
78 | |||
79 | /** |
||
80 | * List of available algorithms |
||
81 | * |
||
82 | * @var array |
||
83 | */ |
||
84 | private $availableAlgorithms = [ |
||
85 | 'enc' => [ |
||
86 | 'aes-128-cbc' => true, |
||
87 | 'aes-128-ecb' => true, |
||
88 | 'aes-192-cbc' => true, |
||
89 | 'aes-192-ecb' => true, |
||
90 | 'aes-256-cbc' => true, |
||
91 | 'aes-256-ecb' => true, |
||
92 | 'base64' => true, |
||
93 | 'bf' => true, |
||
94 | 'bf-cbc' => true, |
||
95 | 'bf-cfb' => true, |
||
96 | 'bf-ecb' => true, |
||
97 | 'bf-ofb' => true, |
||
98 | 'cast' => true, |
||
99 | 'cast-cbc' => true, |
||
100 | 'cast5-cbc' => true, |
||
101 | 'cast5-cfb' => true, |
||
102 | 'cast5-ecb' => true, |
||
103 | 'cast5-ofb' => true, |
||
104 | 'des' => true, |
||
105 | 'des-cbc' => true, |
||
106 | 'des-cfb' => true, |
||
107 | 'des-ecb' => true, |
||
108 | 'des-ede' => true, |
||
109 | 'des-ede-cbc' => true, |
||
110 | 'des-ede-cfb' => true, |
||
111 | 'des-ede-ofb' => true, |
||
112 | 'des-ede3' => true, |
||
113 | 'des-ede3-cbc' => true, |
||
114 | 'des-ede3-cfb' => true, |
||
115 | 'des-ede3-ofb' => true, |
||
116 | 'des-ofb' => true, |
||
117 | 'des3' => true, |
||
118 | 'desx' => true, |
||
119 | 'rc2' => true, |
||
120 | 'rc2-40-cbc' => true, |
||
121 | 'rc2-64-cbc' => true, |
||
122 | 'rc2-cbc' => true, |
||
123 | 'rc2-cfb' => true, |
||
124 | 'rc2-ecb' => true, |
||
125 | 'rc2-ofb' => true, |
||
126 | 'rc4' => true, |
||
127 | 'rc4-40' => true, |
||
128 | 'rc5' => true, |
||
129 | 'rc5-cbc' => true, |
||
130 | 'rc5-cfb' => true, |
||
131 | 'rc5-ecb' => true, |
||
132 | 'rc5-ofb' => true, |
||
133 | 'seed' => true, |
||
134 | 'seed-cbc' => true, |
||
135 | 'seed-cfb' => true, |
||
136 | 'seed-ecb' => true, |
||
137 | 'seed-ofb' => true, |
||
138 | ], |
||
139 | 'smime' => [ |
||
140 | 'des3' => true, |
||
141 | 'des' => true, |
||
142 | 'seed' => true, |
||
143 | 'rc2-40' => true, |
||
144 | 'rc2-64' => true, |
||
145 | 'rc2-128' => true, |
||
146 | 'aes128' => true, |
||
147 | 'aes192' => true, |
||
148 | 'aes256' => true, |
||
149 | ] |
||
150 | ]; |
||
151 | |||
152 | /** |
||
153 | * Keep the not encrypted file |
||
154 | * |
||
155 | * @var boolean |
||
156 | */ |
||
157 | private $deleteUncrypted = true; |
||
158 | |||
159 | /** |
||
160 | 13 | * Constructor. |
|
161 | * |
||
162 | 13 | * @param string $path |
|
163 | 13 | */ |
|
164 | 13 | public function __construct(string $path = '') |
|
165 | { |
||
166 | $this->setup('openssl', $path); |
||
167 | $this->setMaskCandidates(['password']); |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Encrypt a file. |
||
172 | * |
||
173 | 8 | * @param string $file |
|
174 | * @return \phpbu\App\Cli\Executable\OpenSSL |
||
175 | 8 | * @throws Exception |
|
176 | 8 | */ |
|
177 | 8 | public function encryptFile(string $file) : OpenSSL |
|
183 | |||
184 | /** |
||
185 | * Delete the uncrypted data. |
||
186 | 3 | * |
|
187 | * @param boolean $bool |
||
188 | 3 | * @return \phpbu\App\Cli\Executable\OpenSSL |
|
189 | 3 | */ |
|
190 | public function deleteUncrypted(bool $bool) : OpenSSL |
||
195 | |||
196 | /** |
||
197 | * Password to use for encryption. |
||
198 | * |
||
199 | 8 | * @param string $password |
|
200 | * @return \phpbu\App\Cli\Executable\OpenSSL |
||
201 | 8 | * @throws \phpbu\App\Exception |
|
202 | 1 | */ |
|
203 | View Code Duplication | public function usePassword(string $password) : OpenSSL |
|
|
|||
204 | 7 | { |
|
205 | 7 | if (self::MODE_CERT === $this->mode) { |
|
206 | 7 | throw new Exception('Cert file already set'); |
|
207 | } |
||
208 | $this->mode = self::MODE_PASS; |
||
209 | $this->password = $password; |
||
210 | return $this; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Set algorithm to use. |
||
215 | * |
||
216 | 8 | * @param string $algorithm |
|
217 | * @return \phpbu\App\Cli\Executable\OpenSSL |
||
218 | 8 | * @throws \phpbu\App\Exception |
|
219 | 1 | */ |
|
220 | public function useAlgorithm(string $algorithm) : OpenSSL |
||
231 | |||
232 | /** |
||
233 | * Use base64 encoding |
||
234 | 2 | * |
|
235 | * @param bool $encode |
||
236 | 2 | * @return \phpbu\App\Cli\Executable\OpenSSL |
|
237 | 2 | */ |
|
238 | public function encodeBase64(bool $encode) : OpenSSL |
||
243 | |||
244 | /** |
||
245 | * Public key to use. |
||
246 | * |
||
247 | 4 | * @param string $file |
|
248 | * @return \phpbu\App\Cli\Executable\OpenSSL |
||
249 | 4 | * @throws \phpbu\App\Exception |
|
250 | 1 | */ |
|
251 | View Code Duplication | public function useSSLCert(string $file) : OpenSSL |
|
252 | 3 | { |
|
253 | 3 | if (self::MODE_PASS === $this->mode) { |
|
254 | 3 | throw new Exception('Password already set'); |
|
255 | } |
||
256 | $this->mode = self::MODE_CERT; |
||
257 | $this->certFile = $file; |
||
258 | return $this; |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * OpenSSL CommandLine generator. |
||
263 | 9 | * |
|
264 | * @return \SebastianFeldmann\Cli\CommandLine |
||
265 | 9 | * @throws \phpbu\App\Exception |
|
266 | 1 | */ |
|
267 | protected function createCommandLine() : CommandLine |
||
268 | 8 | { |
|
269 | 1 | if (empty($this->sourceFile)) { |
|
270 | throw new Exception('file is missing'); |
||
271 | 7 | } |
|
272 | 1 | if (empty($this->mode)) { |
|
273 | throw new Exception('one of \'password\' or \'cert\' is mandatory'); |
||
274 | } |
||
275 | 6 | if (empty($this->algorithm)) { |
|
276 | 6 | throw new Exception('no algorithm specified'); |
|
277 | 6 | } |
|
278 | |||
279 | $process = new CommandLine(); |
||
280 | 6 | $cmd = new Cmd($this->binary); |
|
281 | 6 | ||
282 | $process->addCommand($cmd); |
||
283 | 6 | ||
284 | $this->setOptions($cmd); |
||
285 | 6 | $this->addDeleteCommand($process); |
|
286 | |||
287 | 6 | return $process; |
|
288 | } |
||
289 | 6 | ||
290 | /** |
||
291 | * Set the openssl command line options |
||
292 | * |
||
293 | * @param \SebastianFeldmann\Cli\Command\Executable $cmd |
||
294 | */ |
||
295 | protected function setOptions(Cmd $cmd) |
||
303 | |||
304 | 6 | /** |
|
305 | * Set command line options for SSL cert encryption. |
||
306 | * |
||
307 | * @param \SebastianFeldmann\Cli\Command\Executable $cmd |
||
308 | */ |
||
309 | protected function setCertOptions(Cmd $cmd) |
||
320 | 2 | ||
321 | 2 | /** |
|
322 | * Set command line options for password encryption |
||
323 | * |
||
324 | * @param \SebastianFeldmann\Cli\Command\Executable $cmd |
||
325 | */ |
||
326 | protected function setPasswordOptions(Cmd $cmd) |
||
338 | 4 | ||
339 | 4 | /** |
|
340 | * Add the 'rm' command to remove the uncrypted file. |
||
341 | * |
||
342 | * @param \SebastianFeldmann\Cli\CommandLine $process |
||
343 | */ |
||
344 | protected function addDeleteCommand(CommandLine $process) |
||
352 | } |
||
353 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.