Skip to content

Commit e6059cc

Browse files
authored
Merge pull request #203 from vitkutny/type-itf14-checksum
ITF14 checksum fix
2 parents 17f981c + a139792 commit e6059cc

2 files changed

Lines changed: 69 additions & 2 deletions

File tree

src/Types/TypeITF14.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
use Picqer\Barcode\Barcode;
66
use Picqer\Barcode\BarcodeBar;
77
use Picqer\Barcode\Exceptions\InvalidCharacterException;
8+
use Picqer\Barcode\Exceptions\InvalidCheckDigitException;
89
use Picqer\Barcode\Exceptions\InvalidLengthException;
910

1011
class TypeITF14 implements TypeInterface
1112
{
1213
/**
1314
* @throws InvalidLengthException
1415
* @throws InvalidCharacterException
16+
* @throws InvalidCheckDigitException
1517
*/
1618
public function getBarcodeData(string $code): Barcode
1719
{
@@ -35,6 +37,10 @@ public function getBarcodeData(string $code): Barcode
3537

3638
if (strlen($code) === 13) {
3739
$code .= $this->getChecksum($code);
40+
} elseif (substr($code, -1) !== $this->getChecksum(substr($code, 0, -1))) {
41+
// If length of given barcode is same as final length, barcode is including checksum
42+
// Make sure that checksum is the same as we calculated
43+
throw new InvalidCheckDigitException();
3844
}
3945

4046
$barcode = new Barcode($code);
@@ -73,8 +79,8 @@ private function getChecksum(string $code): string
7379
$total = 0;
7480

7581
for ($charIndex = 0; $charIndex <= (strlen($code) - 1); $charIndex++) {
76-
$integerOfChar = intval($code . substr($charIndex, 1));
77-
$total += $integerOfChar * (($charIndex === 0 || $charIndex % 2 === 0) ? 3 : 1);
82+
$integerOfChar = intval($code[$charIndex]);
83+
$total += $integerOfChar * ($charIndex % 2 === 0 ? 3 : 1);
7884
}
7985

8086
$checksum = 10 - ($total % 10);

tests/ChecksumBarcodeTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
use Picqer\Barcode\Exceptions\BarcodeException;
5+
use Picqer\Barcode\Exceptions\InvalidCheckDigitException;
6+
use Picqer\Barcode\Types\TypeEan13;
7+
use Picqer\Barcode\Types\TypeInterface;
8+
use Picqer\Barcode\Types\TypeITF14;
9+
10+
class ChecksumBarcodeTest extends TestCase
11+
{
12+
private const VALID_BARCODES = [
13+
['type' => TypeEan13::class, 'barcodes' => [
14+
'081231723897' => '0812317238973',
15+
'004900000463' => '0049000004632',
16+
]],
17+
['type' => TypeITF14::class, 'barcodes' => [
18+
'0001234560001' => '00012345600012',
19+
'0540014128876' => '05400141288766',
20+
]],
21+
];
22+
private const INVALID_BARCODES = [
23+
['type' => TypeEan13::class, 'barcodes' => ['0812317238972', '0049000004633']],
24+
['type' => TypeITF14::class, 'barcodes' => ['00012345600016', '05400141288762']],
25+
];
26+
27+
public function testAllValidBarcodeTypes()
28+
{
29+
foreach (self::VALID_BARCODES as $barcodeTestSet) {
30+
$barcodeType = $this->getBarcodeType($barcodeTestSet['type']);
31+
32+
foreach ($barcodeTestSet['barcodes'] as $testBarcode => $validBarcode) {
33+
$this->assertEquals($validBarcode, $barcodeType->getBarcodeData($testBarcode)->getBarcode());
34+
}
35+
}
36+
}
37+
38+
public function testAllInvalidBarcodeTypes()
39+
{
40+
foreach (self::INVALID_BARCODES as $barcodeTestSet) {
41+
$barcodeType = $this->getBarcodeType($barcodeTestSet['type']);
42+
43+
foreach ($barcodeTestSet['barcodes'] as $invalidBarcode) {
44+
try {
45+
$barcodeType->getBarcodeData($invalidBarcode)->getBarcode();
46+
} catch (BarcodeException $exception) {
47+
$this->assertInstanceOf(InvalidCheckDigitException::class, $exception);
48+
continue;
49+
}
50+
51+
$this->assertTrue(false, sprintf('Exception was not thrown for barcode "%s".', $invalidBarcode));
52+
}
53+
}
54+
}
55+
56+
57+
private function getBarcodeType(string $typeClass): TypeInterface
58+
{
59+
return new $typeClass;
60+
}
61+
}

0 commit comments

Comments
 (0)