Create "Luhn" rule

This commit is contained in:
mazanax 2017-08-18 14:47:36 +03:00 committed by Henrique Moody
parent 5f50541086
commit 8b3790103e
No known key found for this signature in database
GPG key ID: 221E9281655813A6
9 changed files with 145 additions and 35 deletions

View file

@ -44,3 +44,4 @@ See also:
- [Bank](Bank.md)
- [BankAccount](BankAccount.md)
- [Bic](Bic.md)
- [Luhn](Luhn.md)

23
docs/Luhn.md Normal file
View file

@ -0,0 +1,23 @@
# Luhn
- `Luhn()`
Validate whether a given input is a [Luhn][] number.
```php
v::luhn()->validate('2222400041240011'); // true
v::luhn()->validate('respect!'); // false
```
## Changelog
Version | Description
--------|-------------
2.0.0 | Created
[Luhn]: https://en.wikipedia.org/wiki/Luhn_algorithm
***
See also:
- [CreditCard](CreditCard.md)
- [Imei](Imei.md)

View file

@ -187,6 +187,7 @@
- [Imei](Imei.md)
- [Ip](Ip.md)
- [Json](Json.md)
- [Luhn](Luhn.md)
- [MacAddress](MacAddress.md)
- [NfeAccessKey](NfeAccessKey.md)
- [Nif](Nif.md)
@ -286,6 +287,7 @@
- [LeapYear](LeapYear.md)
- [Length](Length.md)
- [Lowercase](Lowercase.md)
- [Luhn](Luhn.md)
- [MacAddress](MacAddress.md)
- [Max](Max.md)
- [Mimetype](Mimetype.md)

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Exceptions;
class LuhnException extends ValidationException
{
public static $defaultTemplates = [
self::MODE_DEFAULT => [
self::STANDARD => '{{name}} must be a valid Luhn number',
],
self::MODE_NEGATIVE => [
self::STANDARD => '{{name}} must not be a valid Luhn number',
],
];
}

View file

@ -64,40 +64,13 @@ class CreditCard extends AbstractRule
return false;
}
if (!$this->verifyMod10($input)) {
if (!(new Luhn())->validate($input)) {
return false;
}
return $this->verifyBrand($input);
}
/**
* Returns whether the input matches the Luhn algorithm or not.
*
* @param string $input
*
* @return bool
*/
private function verifyMod10($input)
{
$sum = 0;
$input = strrev($input);
for ($i = 0; $i < mb_strlen($input); ++$i) {
$current = mb_substr($input, $i, 1);
if ($i % 2 == 1) {
$current *= 2;
if ($current > 9) {
$firstDigit = $current % 10;
$secondDigit = ($current - $firstDigit) / 10;
$current = $firstDigit + $secondDigit;
}
}
$sum += $current;
}
return $sum % 10 == 0;
}
/**
* Returns whether the input matches the defined credit card brand or not.
*

View file

@ -33,12 +33,6 @@ class Imei extends AbstractRule
return false;
}
$sum = 0;
for ($position = 0; $position < (self::IMEI_SIZE - 1); ++$position) {
$number = $numbers[$position] * (($position % 2) + 1);
$sum += ($number % 10) + intval($number / 10);
}
return (ceil($sum / 10) * 10) - $sum == $numbers[14];
return (new Luhn())->validate($numbers);
}
}

49
library/Rules/Luhn.php Normal file
View file

@ -0,0 +1,49 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Rules;
/**
* @link https://en.wikipedia.org/wiki/Luhn_algorithm
*/
class Luhn extends AbstractRule
{
/**
* {@inheritdoc}
*/
public function validate($input)
{
if (!(new Digit())->validate($input)) {
return false;
}
return $this->isValid($input);
}
private function isValid($input): bool
{
$sum = 0;
$numDigits = strlen($input);
$parity = $numDigits % 2;
for ($i = 0; $i < $numDigits; ++$i) {
$digit = substr($input, $i, 1);
if ($parity == ($i % 2)) {
$digit <<= 1;
if (9 < $digit) {
$digit = $digit - 9;
}
}
$sum += $digit;
}
return 0 == ($sum % 10);
}
}

View file

@ -95,6 +95,7 @@ use Respect\Validation\Rules\Key;
* @method static Validator leapYear()
* @method static Validator length(int $min = null, int $max = null, bool $inclusive = true)
* @method static Validator lowercase()
* @method static Validator luhn()
* @method static Validator macAddress()
* @method static Validator max(mixed $maxValue, bool $inclusive = true)
* @method static Validator mimetype(string $mimetype)

View file

@ -0,0 +1,43 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Rules;
/**
* @group rule
* @covers \Respect\Validation\Rules\Luhn
*/
class LuhnTest extends RuleTestCase
{
public function providerForValidInput()
{
$rule = new Luhn();
return [
[$rule, '2222400041240011'],
[$rule, '340316193809364'],
[$rule, '6011000990139424'],
[$rule, '2223000048400011'],
];
}
public function providerForInvalidInput()
{
$rule = new Luhn();
return [
[$rule, '2222400041240021'],
[$rule, '340316193809334'],
[$rule, '6011000990139421'],
[$rule, '2223000048400010'],
];
}
}