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 |
||
67 | class CirclesRemote extends Base { |
||
68 | |||
69 | |||
70 | use TNC21WellKnown; |
||
71 | use TStringTools; |
||
72 | |||
73 | |||
74 | /** @var RemoteRequest */ |
||
75 | private $remoteRequest; |
||
76 | |||
77 | /** @var GlobalScaleService */ |
||
78 | private $globalScaleService; |
||
79 | |||
80 | /** @var RemoteStreamService */ |
||
81 | private $remoteStreamService; |
||
82 | |||
83 | /** @var ConfigService */ |
||
84 | private $configService; |
||
85 | |||
86 | |||
87 | /** @var InputInterface */ |
||
88 | private $input; |
||
89 | |||
90 | /** @var OutputInterface */ |
||
91 | private $output; |
||
92 | |||
93 | |||
94 | /** |
||
95 | * CirclesRemote constructor. |
||
96 | * |
||
97 | * @param RemoteRequest $remoteRequest |
||
98 | * @param GlobalScaleService $globalScaleService |
||
99 | * @param RemoteStreamService $remoteStreamService |
||
100 | * @param ConfigService $configService |
||
101 | */ |
||
102 | public function __construct( |
||
115 | |||
116 | |||
117 | /** |
||
118 | * |
||
119 | */ |
||
120 | protected function configure() { |
||
127 | |||
128 | |||
129 | /** |
||
130 | * @param InputInterface $input |
||
131 | * @param OutputInterface $output |
||
132 | * |
||
133 | * @return int |
||
134 | * @throws Exception |
||
135 | */ |
||
136 | protected function execute(InputInterface $input, OutputInterface $output): int { |
||
150 | |||
151 | |||
152 | /** |
||
153 | * @param string $host |
||
154 | * |
||
155 | * @throws RemoteUidException |
||
156 | * @throws RequestNetworkException |
||
157 | * @throws SignatoryException |
||
158 | * @throws SignatureException |
||
159 | * @throws RequestContentException |
||
160 | * @throws WellKnownLinkNotFoundException |
||
161 | */ |
||
162 | private function requestInstance(string $host): void { |
||
163 | $webfinger = $this->getWebfinger($host, Application::APP_SUBJECT); |
||
164 | View Code Duplication | if ($this->input->getOption('all')) { |
|
|
|||
165 | $this->output->writeln('- Webfinger on <info>' . $host . '</info>'); |
||
166 | $this->output->writeln(json_encode($webfinger, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); |
||
167 | $this->output->writeln(''); |
||
168 | } |
||
169 | |||
170 | View Code Duplication | if ($this->input->getOption('all')) { |
|
171 | $circleLink = $this->extractLink(Application::APP_REL, $webfinger); |
||
172 | $this->output->writeln('- Information about Circles app on <info>' . $host . '</info>'); |
||
173 | $this->output->writeln(json_encode($circleLink, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); |
||
174 | $this->output->writeln(''); |
||
175 | } |
||
176 | |||
177 | $this->output->writeln('- Available services on <info>' . $host . '</info>'); |
||
178 | foreach ($webfinger->getLinks() as $link) { |
||
179 | $app = $link->getProperty('name'); |
||
180 | $ver = $link->getProperty('version'); |
||
181 | if ($app !== '') { |
||
182 | $app .= ' '; |
||
183 | } |
||
184 | if ($ver !== '') { |
||
185 | $ver = 'v' . $ver; |
||
186 | } |
||
187 | |||
188 | $this->output->writeln(' * ' . $link->getRel() . ' ' . $app . $ver); |
||
189 | } |
||
190 | $this->output->writeln(''); |
||
191 | |||
192 | $this->output->writeln('- Resources related to Circles on <info>' . $host . '</info>'); |
||
193 | $resource = $this->getResourceData($host, Application::APP_SUBJECT, Application::APP_REL); |
||
194 | $this->output->writeln(json_encode($resource, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); |
||
195 | $this->output->writeln(''); |
||
196 | |||
197 | |||
198 | $tempUid = $resource->g('uid'); |
||
199 | $this->output->writeln( |
||
200 | '- Confirming UID=' . $tempUid . ' from parsed Signatory at <info>' . $host . '</info>' |
||
201 | ); |
||
202 | |||
203 | try { |
||
204 | $remoteSignatory = $this->remoteStreamService->retrieveSignatory($resource->g('id'), true); |
||
205 | $this->output->writeln(' * No SignatureException: <info>Identity authed</info>'); |
||
206 | } catch (SignatureException $e) { |
||
207 | $this->output->writeln( |
||
208 | '<error>' . $host . ' cannot auth its identity: ' . $e->getMessage() . '</error>' |
||
209 | ); |
||
210 | |||
211 | return; |
||
212 | } |
||
213 | |||
214 | $this->output->writeln(' * Found <info>' . $remoteSignatory->getUid() . '</info>'); |
||
215 | if ($remoteSignatory->getUid(true) !== $tempUid) { |
||
216 | $this->output->writeln('<error>looks like ' . $host . ' is faking its identity'); |
||
217 | |||
218 | return; |
||
219 | } |
||
220 | |||
221 | $this->output->writeln(''); |
||
222 | |||
223 | $testUrl = $resource->g('test'); |
||
224 | $this->output->writeln('- Testing signed payload on <info>' . $testUrl . '</info>'); |
||
225 | |||
226 | try { |
||
227 | $localSignatory = $this->remoteStreamService->getAppSignatory(); |
||
228 | } catch (SignatoryException $e) { |
||
229 | $this->output->writeln( |
||
230 | '<error>Federated Circles not enabled locally. Please run ./occ circles:remote:init</error>' |
||
231 | ); |
||
232 | |||
233 | return; |
||
234 | } |
||
235 | |||
236 | $payload = [ |
||
237 | 'test' => 42, |
||
238 | 'token' => $this->uuid() |
||
239 | ]; |
||
240 | $signedRequest = $this->outgoingTest($testUrl, $payload); |
||
241 | $this->output->writeln(' * Payload: '); |
||
242 | $this->output->writeln(json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); |
||
243 | $this->output->writeln(''); |
||
244 | |||
245 | $this->output->writeln(' * Clear Signature: '); |
||
246 | $this->output->writeln('<comment>' . $signedRequest->getClearSignature() . '</comment>'); |
||
247 | $this->output->writeln(''); |
||
248 | |||
249 | $this->output->writeln(' * Signed Signature (base64 encoded): '); |
||
250 | $this->output->writeln( |
||
251 | '<comment>' . base64_encode($signedRequest->getSignedSignature()) . '</comment>' |
||
252 | ); |
||
253 | $this->output->writeln(''); |
||
254 | |||
255 | $result = $signedRequest->getOutgoingRequest()->getResult(); |
||
256 | $code = $result->getStatusCode(); |
||
257 | $this->output->writeln(' * Result: ' . (($code === 200) ? '<info>' . $code . '</info>' : $code)); |
||
258 | $this->output->writeln( |
||
259 | json_encode(json_decode($result->getContent(), true), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) |
||
260 | ); |
||
261 | $this->output->writeln(''); |
||
262 | |||
263 | View Code Duplication | if ($this->input->getOption('all')) { |
|
264 | $this->output->writeln(''); |
||
265 | $this->output->writeln('<info>### Complete report ###</info>'); |
||
266 | $this->output->writeln(json_encode($signedRequest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); |
||
267 | $this->output->writeln(''); |
||
268 | } |
||
269 | |||
270 | if ($remoteSignatory->getUid() !== $localSignatory->getUid()) { |
||
271 | $remoteSignatory->setInstance($host); |
||
272 | try { |
||
273 | $stored = new RemoteInstance(); |
||
274 | $this->remoteStreamService->confirmValidRemote($remoteSignatory, $stored); |
||
275 | $this->output->writeln( |
||
276 | '<info>The remote instance ' . $host |
||
277 | . ' is already known with this current identity</info>' |
||
278 | ); |
||
279 | |||
280 | View Code Duplication | if ($remoteSignatory->getInstance() !== $stored->getInstance()) { |
|
281 | $this->output->writeln( |
||
282 | '- updating host from ' . $stored->getInstance() . ' to ' |
||
283 | . $remoteSignatory->getInstance() |
||
284 | ); |
||
285 | $this->remoteStreamService->update($remoteSignatory, RemoteStreamService::UPDATE_INSTANCE); |
||
286 | } |
||
287 | View Code Duplication | if ($remoteSignatory->getId() !== $stored->getId()) { |
|
288 | $this->output->writeln( |
||
289 | '- updating href/Id from ' . $stored->getId() . ' to ' |
||
290 | . $remoteSignatory->getId() |
||
291 | ); |
||
292 | $this->remoteStreamService->update($remoteSignatory, RemoteStreamService::UPDATE_HREF); |
||
293 | } |
||
294 | |||
295 | } catch (RemoteUidException $e) { |
||
296 | $this->updateRemote($remoteSignatory); |
||
297 | } catch (RemoteNotFoundException $e) { |
||
298 | $this->saveRemote($remoteSignatory); |
||
299 | } |
||
300 | } |
||
301 | |||
302 | } |
||
303 | |||
304 | |||
305 | /** |
||
306 | * @param RemoteInstance $remoteSignatory |
||
307 | * |
||
308 | * @throws RemoteUidException |
||
309 | */ |
||
310 | View Code Duplication | private function saveRemote(RemoteInstance $remoteSignatory) { |
|
328 | |||
329 | |||
330 | /** |
||
331 | * @param RemoteInstance $remoteSignatory |
||
332 | * |
||
333 | * @throws RemoteUidException |
||
334 | */ |
||
335 | View Code Duplication | private function updateRemote(RemoteInstance $remoteSignatory): void { |
|
357 | |||
358 | |||
359 | /** |
||
360 | * @param string $remote |
||
361 | * @param array $payload |
||
362 | * |
||
363 | * @return NC21SignedRequest |
||
364 | * @throws RequestNetworkException |
||
365 | * @throws SignatoryException |
||
366 | */ |
||
367 | private function outgoingTest(string $remote, array $payload): NC21SignedRequest { |
||
381 | |||
382 | |||
383 | /** |
||
384 | * |
||
385 | */ |
||
386 | private function checkKnownInstance(): void { |
||
390 | |||
391 | |||
392 | /** |
||
393 | * |
||
394 | */ |
||
395 | private function verifyGSInstances(): void { |
||
408 | |||
409 | |||
410 | /** |
||
411 | * @param string $instance |
||
412 | */ |
||
413 | private function syncGSInstance(string $instance): void { |
||
426 | |||
427 | |||
428 | private function checkRemoteInstances(): void { |
||
459 | |||
460 | } |
||
461 | |||
462 |
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.