Skip to content

Commit 0d9152f

Browse files
authored
Add MissingCheckDigitException and common interface for all exceptions. Add tests for exceptions. (#23)
* create exceptions specific for this library * lint * add tests for argument is not numeric * add test for missing check digit exception * add clarification * cleanup * cleanup
1 parent 93a47dc commit 0d9152f

9 files changed

+154
-48
lines changed

composer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,9 @@
3939
"phpunit/phpunit": "^6.0",
4040
"friendsofphp/php-cs-fixer": "^2.15",
4141
"php-coveralls/php-coveralls": "^2.1"
42+
},
43+
"scripts": {
44+
"lint": "php-cs-fixer fix",
45+
"test": "phpunit --configuration phpunit.xml"
4246
}
4347
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2018 Niklas Ekman
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
9+
* this software and associated documentation files (the "Software"), to deal in
10+
* the Software without restriction, including without limitation the rights to
11+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12+
* the Software, and to permit persons to whom the Software is furnished to do so,
13+
* subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
declare(strict_types=1);
27+
28+
namespace Nekman\LuhnAlgorithm\Contract;
29+
30+
/**
31+
* Base interface for all thrown exceptions in this library.
32+
*/
33+
interface LuhnAlgorithmExceptionInterface extends \Throwable
34+
{
35+
}

src/Contract/LuhnAlgorithmInterface.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
namespace Nekman\LuhnAlgorithm\Contract;
2929

30+
use Nekman\LuhnAlgorithm\Exceptions\MissingCheckDigitException;
31+
3032
/**
3133
* Handles the Luhn Algorithm.
3234
*
@@ -40,6 +42,8 @@ interface LuhnAlgorithmInterface
4042
* @param NumberInterface $number The number to validate.
4143
*
4244
* @return bool true if number is valid, false otherwise.
45+
*
46+
* @throws MissingCheckDigitException If the check digit in the number is not set.
4347
*/
4448
public function isValid(NumberInterface $number): bool;
4549

@@ -49,7 +53,6 @@ public function isValid(NumberInterface $number): bool;
4953
* @param NumberInterface $number The number to calculate the check digit for.
5054
*
5155
* @return int The check digit.
52-
*
5356
*/
5457
public function calcCheckDigit(NumberInterface $number): int;
5558

@@ -59,7 +62,6 @@ public function calcCheckDigit(NumberInterface $number): int;
5962
* @param NumberInterface $number The number to calculate the checksum for.
6063
*
6164
* @return int The checksum.
62-
*
6365
*/
6466
public function calcChecksum(NumberInterface $number): int;
6567
}

src/ArgumentIsNotNumericException.php renamed to src/Exceptions/ArgumentIsNotNumericException.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525

2626
declare(strict_types=1);
2727

28-
namespace Nekman\LuhnAlgorithm;
28+
namespace Nekman\LuhnAlgorithm\Exceptions;
2929

30-
class ArgumentIsNotNumericException extends \InvalidArgumentException
30+
use Nekman\LuhnAlgorithm\Contract\LuhnAlgorithmExceptionInterface;
31+
32+
/**
33+
* Indicates that an argument should be numeric, but is in fact not.
34+
*/
35+
class ArgumentIsNotNumericException extends \InvalidArgumentException implements LuhnAlgorithmExceptionInterface
3136
{
32-
/**
33-
* ArgumentIsNotNumericException constructor.
34-
* @param string $number
35-
*/
3637
public function __construct(string $number)
3738
{
38-
parent::__construct("Expects \$number to be a number, \"{$number}\" given.", 0, null);
39+
parent::__construct("Expects \$number to be a number, \"{$number}\" given.");
3940
}
4041
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2018 Niklas Ekman
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
9+
* this software and associated documentation files (the "Software"), to deal in
10+
* the Software without restriction, including without limitation the rights to
11+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12+
* the Software, and to permit persons to whom the Software is furnished to do so,
13+
* subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
declare(strict_types=1);
27+
28+
namespace Nekman\LuhnAlgorithm\Exceptions;
29+
30+
use Nekman\LuhnAlgorithm\Contract\LuhnAlgorithmExceptionInterface;
31+
32+
/**
33+
* Indicates that the check digit should be present, but is in fact not.
34+
*/
35+
class MissingCheckDigitException extends \InvalidArgumentException implements LuhnAlgorithmExceptionInterface
36+
{
37+
}

src/LuhnAlgorithm.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,29 @@
2929

3030
use Nekman\LuhnAlgorithm\Contract\LuhnAlgorithmInterface;
3131
use Nekman\LuhnAlgorithm\Contract\NumberInterface;
32+
use Nekman\LuhnAlgorithm\Exceptions\MissingCheckDigitException;
3233

3334
/**
3435
* {@inheritdoc}
3536
*/
3637
class LuhnAlgorithm implements LuhnAlgorithmInterface
3738
{
39+
/**
40+
* @internal The intended way to instantiate this object is through the factory.
41+
*
42+
* @see LuhnAlgorithmFactory
43+
*/
44+
public function __construct()
45+
{
46+
}
47+
3848
/**
3949
* {@inheritDoc}
4050
*/
4151
public function isValid(NumberInterface $number): bool
4252
{
4353
if ($number->getCheckDigit() === null) {
44-
throw new \InvalidArgumentException("Check digit is null.");
54+
throw new MissingCheckDigitException("Check digit is null.");
4555
}
4656

4757
$checksum = $this->calcChecksum($number) + $number->getCheckDigit();

src/Number.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
namespace Nekman\LuhnAlgorithm;
2929

3030
use Nekman\LuhnAlgorithm\Contract\NumberInterface;
31+
use Nekman\LuhnAlgorithm\Exceptions\ArgumentIsNotNumericException;
3132

3233
/**
3334
* Input for the Luhn Algorithm contains a number and a check digit.
@@ -45,9 +46,10 @@ class Number implements NumberInterface
4546
private $checkDigit;
4647

4748
/**
48-
* Input constructor.
4949
* @param string $number The number.
5050
* @param int|null $checkDigit [Optional] The check digit for the number.
51+
*
52+
* @throws ArgumentIsNotNumericException If the number input does not consist entirely of numbers.
5153
*/
5254
public function __construct(string $number, int $checkDigit = null)
5355
{
@@ -66,6 +68,8 @@ public function __construct(string $number, int $checkDigit = null)
6668
* @param string $input The input that contains the check digit already.
6769
*
6870
* @return self
71+
*
72+
* @throws ArgumentIsNotNumericException If the input does not consist entirely of numbers.
6973
*/
7074
public static function fromString(string $input): self
7175
{

tests/LuhnAlgorithmTest.php

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
namespace Nekman\LuhnAlgorithm\Test;
2727

28+
use Nekman\LuhnAlgorithm\Contract\LuhnAlgorithmExceptionInterface;
29+
use Nekman\LuhnAlgorithm\Exceptions\MissingCheckDigitException;
2830
use Nekman\LuhnAlgorithm\LuhnAlgorithm;
2931
use Nekman\LuhnAlgorithm\Number;
3032
use PHPUnit\Framework\TestCase;
@@ -46,65 +48,70 @@ protected function setUp()
4648
/**
4749
* @dataProvider provideIsValid_success
4850
*/
49-
public function testIsValid_success($number, $expected, $purpose)
51+
public function testIsValid_success($number, $expected)
5052
{
51-
$this->assertEquals($expected, $this->luhn->isValid($number), $purpose);
53+
$this->assertEquals($expected, $this->luhn->isValid($number));
5254
}
5355

5456
public function provideIsValid_success()
5557
{
5658
return [
57-
[new Number('12345', 5), true, "Valid number"],
58-
[new Number('0', 0), true, "Zero"],
59-
[new Number('92233720368547758072', 8), true, "Larger than INT_MAX"],
60-
[new Number('12345', 6), false, "Invalid number"],
59+
"Valid number" => [new Number('12345', 5), true],
60+
"Zero" => [new Number('0', 0), true],
61+
"Larger than INT_MAX" => [new Number('92233720368547758072', 8), true],
62+
"Invalid number" => [new Number('12345', 6), false],
63+
"Swedish company organization ID" => [new Number(559114884, 5), true],
64+
"Swedish organization number" => [new Number(640319261, 7), true],
6165
];
6266
}
6367

6468
/**
6569
* @dataProvider provideIsValid_failure
6670
*/
67-
public function testIsValid_failure($number, $exception, $purpose)
71+
public function testIsValid_failure($number, $exception)
6872
{
69-
$this->expectException($exception, $purpose);
73+
$this->expectException($exception);
7074
$this->luhn->isValid($number);
7175
}
7276

7377
public function provideIsValid_failure()
7478
{
7579
return [
76-
[new Number(123, null), \InvalidArgumentException::class, "Invalid argument"],
80+
"Invalid argument" => [new Number(123, null), \InvalidArgumentException::class],
81+
"Should be MissingCheckDigitException" => [new Number(123, null), MissingCheckDigitException::class],
82+
"Should be LuhnAlgorithmExceptionInterface" => [new Number(123, null), LuhnAlgorithmExceptionInterface::class],
7783
];
7884
}
7985

8086
/**
8187
* @dataProvider provideCalcChecksum_success
8288
*/
83-
public function testCalcChecksum_success($number, $expected, $purpose)
89+
public function testCalcChecksum_success($number, $expected)
8490
{
85-
$this->assertEquals($expected, $this->luhn->calcChecksum($number), $purpose);
91+
$this->assertEquals($expected, $this->luhn->calcChecksum($number));
8692
}
8793

8894
public function provideCalcChecksum_success()
8995
{
9096
return [
91-
[new Number(3199723370002), 50, "Valid checksum"],
97+
"Valid checksum" => [new Number(3199723370002), 50],
9298
];
9399
}
94100

95101
/**
96102
* @dataProvider provideCalcCheckDigit_success
97103
*/
98-
public function testCalcCheckDigit_success($number, $expected, $purpose)
104+
public function testCalcCheckDigit_success($number, $expected)
99105
{
100106
$this->assertEquals($expected, $this->luhn->calcCheckDigit($number));
101107
}
102108

103109
public function provideCalcCheckDigit_success()
104110
{
105111
return [
106-
[new Number(12345), 5, "Valid number"],
107-
[new Number(559114884), 5, "Swedish company organization ID"],
112+
"Valid number" => [new Number(12345), 5],
113+
"Swedish company organization ID" => [new Number(559114884), 5],
114+
"Swedish organization number" => [new Number(640319261), 7],
108115
];
109116
}
110117
}

0 commit comments

Comments
 (0)