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 |
||
| 48 | class StepUpAuthenticationService |
||
| 49 | { |
||
| 50 | /** |
||
| 51 | * @var \Surfnet\StepupBundle\Service\LoaResolutionService |
||
| 52 | */ |
||
| 53 | private $loaResolutionService; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var \Surfnet\StepupGateway\GatewayBundle\Entity\SecondFactorRepository |
||
| 57 | */ |
||
| 58 | private $secondFactorRepository; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var \Surfnet\StepupGateway\ApiBundle\Service\YubikeyService |
||
| 62 | */ |
||
| 63 | private $yubikeyService; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * @var \Surfnet\StepupBundle\Service\SmsSecondFactorService |
||
| 67 | */ |
||
| 68 | private $smsService; |
||
| 69 | |||
| 70 | /** |
||
| 71 | * @var \Symfony\Component\Translation\TranslatorInterface |
||
| 72 | */ |
||
| 73 | private $translator; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * @var \Psr\Log\LoggerInterface |
||
| 77 | */ |
||
| 78 | private $logger; |
||
| 79 | |||
| 80 | /** |
||
| 81 | * @param LoaResolutionService $loaResolutionService |
||
| 82 | * @param SecondFactorRepository $secondFactorRepository |
||
| 83 | * @param YubikeyService $yubikeyService |
||
| 84 | * @param SmsSecondFactorService $smsService |
||
| 85 | * @param TranslatorInterface $translator |
||
| 86 | * @param LoggerInterface $logger |
||
| 87 | */ |
||
| 88 | public function __construct( |
||
| 103 | |||
| 104 | /** |
||
| 105 | * @param string $identityNameId |
||
| 106 | * @param Loa $requiredLoa |
||
| 107 | * @return \Doctrine\Common\Collections\ArrayCollection |
||
| 108 | */ |
||
| 109 | public function determineViableSecondFactors( |
||
| 120 | |||
| 121 | /** |
||
| 122 | * @param string $requestedLoa |
||
| 123 | * @param ServiceProvider $serviceProvider |
||
| 124 | * @param IdentityProvider $authenticatingIdp |
||
|
|
|||
| 125 | * @return null|Loa |
||
| 126 | * |
||
| 127 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) see https://www.pivotaltracker.com/story/show/96065350 |
||
| 128 | * @SuppressWarnings(PHPMD.NPathComplexity) see https://www.pivotaltracker.com/story/show/96065350 |
||
| 129 | */ |
||
| 130 | public function resolveHighestRequiredLoa( |
||
| 206 | |||
| 207 | /** |
||
| 208 | * Returns whether the given Loa identifier identifies the minimum Loa, intrinsic to being authenticated via an IdP. |
||
| 209 | * |
||
| 210 | * @param Loa $loa |
||
| 211 | * @return bool |
||
| 212 | */ |
||
| 213 | public function isIntrinsicLoa(Loa $loa) |
||
| 217 | |||
| 218 | /** |
||
| 219 | * @param VerifyYubikeyOtpCommand $command |
||
| 220 | * @return YubikeyOtpVerificationResult |
||
| 221 | */ |
||
| 222 | public function verifyYubikeyOtp(VerifyYubikeyOtpCommand $command) |
||
| 223 | { |
||
| 224 | /** @var SecondFactor $secondFactor */ |
||
| 225 | $secondFactor = $this->secondFactorRepository->findOneBySecondFactorId($command->secondFactorId); |
||
| 226 | |||
| 227 | $requester = new Requester(); |
||
| 228 | $requester->identity = $secondFactor->identityId; |
||
| 229 | $requester->institution = $secondFactor->institution; |
||
| 230 | |||
| 231 | $otp = new ApiOtp(); |
||
| 232 | $otp->value = $command->otp; |
||
| 233 | |||
| 234 | $result = $this->yubikeyService->verify($otp, $requester); |
||
| 235 | |||
| 236 | if (!$result->isSuccessful()) { |
||
| 237 | return new YubikeyOtpVerificationResult(YubikeyOtpVerificationResult::RESULT_OTP_VERIFICATION_FAILED, null); |
||
| 238 | } |
||
| 239 | |||
| 240 | $otp = YubikeyOtp::fromString($command->otp); |
||
| 241 | $publicId = YubikeyPublicId::fromOtp($otp); |
||
| 242 | |||
| 243 | if (!$publicId->equals(new YubikeyPublicId($secondFactor->secondFactorIdentifier))) { |
||
| 244 | return new YubikeyOtpVerificationResult( |
||
| 245 | YubikeyOtpVerificationResult::RESULT_PUBLIC_ID_DID_NOT_MATCH, |
||
| 246 | $publicId |
||
| 247 | ); |
||
| 248 | } |
||
| 249 | |||
| 250 | return new YubikeyOtpVerificationResult(YubikeyOtpVerificationResult::RESULT_PUBLIC_ID_MATCHED, $publicId); |
||
| 251 | } |
||
| 252 | |||
| 253 | /** |
||
| 254 | * @param string $secondFactorId |
||
| 255 | * @return string |
||
| 256 | */ |
||
| 257 | public function getSecondFactorIdentifier($secondFactorId) |
||
| 264 | |||
| 265 | /** |
||
| 266 | * @return int |
||
| 267 | */ |
||
| 268 | public function getSmsOtpRequestsRemainingCount() |
||
| 272 | |||
| 273 | /** |
||
| 274 | * @return int |
||
| 275 | */ |
||
| 276 | public function getSmsMaximumOtpRequestsCount() |
||
| 280 | |||
| 281 | /** |
||
| 282 | * @param SendSmsChallengeCommand $command |
||
| 283 | * @return bool |
||
| 284 | */ |
||
| 285 | public function sendSmsChallenge(SendSmsChallengeCommand $command) |
||
| 300 | |||
| 301 | /** |
||
| 302 | * @param VerifyPossessionOfPhoneCommand $command |
||
| 303 | * @return OtpVerification |
||
| 304 | */ |
||
| 305 | public function verifySmsChallenge(VerifyPossessionOfPhoneCommand $command) |
||
| 309 | |||
| 310 | public function clearSmsVerificationState() |
||
| 314 | } |
||
| 315 |
This check looks for
@paramannotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.