Skip to content

Commit

Permalink
Merge pull request #203 from vitkutny/type-itf14-checksum
Browse files Browse the repository at this point in the history
ITF14 checksum fix
  • Loading branch information
casperbakker authored Sep 18, 2024
2 parents 17f981c + a139792 commit e6059cc
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/Types/TypeITF14.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
use Picqer\Barcode\Barcode;
use Picqer\Barcode\BarcodeBar;
use Picqer\Barcode\Exceptions\InvalidCharacterException;
use Picqer\Barcode\Exceptions\InvalidCheckDigitException;
use Picqer\Barcode\Exceptions\InvalidLengthException;

class TypeITF14 implements TypeInterface
{
/**
* @throws InvalidLengthException
* @throws InvalidCharacterException
* @throws InvalidCheckDigitException
*/
public function getBarcodeData(string $code): Barcode
{
Expand All @@ -35,6 +37,10 @@ public function getBarcodeData(string $code): Barcode

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

$barcode = new Barcode($code);
Expand Down Expand Up @@ -73,8 +79,8 @@ private function getChecksum(string $code): string
$total = 0;

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

$checksum = 10 - ($total % 10);
Expand Down
61 changes: 61 additions & 0 deletions tests/ChecksumBarcodeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

use PHPUnit\Framework\TestCase;
use Picqer\Barcode\Exceptions\BarcodeException;
use Picqer\Barcode\Exceptions\InvalidCheckDigitException;
use Picqer\Barcode\Types\TypeEan13;
use Picqer\Barcode\Types\TypeInterface;
use Picqer\Barcode\Types\TypeITF14;

class ChecksumBarcodeTest extends TestCase
{
private const VALID_BARCODES = [
['type' => TypeEan13::class, 'barcodes' => [
'081231723897' => '0812317238973',
'004900000463' => '0049000004632',
]],
['type' => TypeITF14::class, 'barcodes' => [
'0001234560001' => '00012345600012',
'0540014128876' => '05400141288766',
]],
];
private const INVALID_BARCODES = [
['type' => TypeEan13::class, 'barcodes' => ['0812317238972', '0049000004633']],
['type' => TypeITF14::class, 'barcodes' => ['00012345600016', '05400141288762']],
];

public function testAllValidBarcodeTypes()
{
foreach (self::VALID_BARCODES as $barcodeTestSet) {
$barcodeType = $this->getBarcodeType($barcodeTestSet['type']);

foreach ($barcodeTestSet['barcodes'] as $testBarcode => $validBarcode) {
$this->assertEquals($validBarcode, $barcodeType->getBarcodeData($testBarcode)->getBarcode());
}
}
}

public function testAllInvalidBarcodeTypes()
{
foreach (self::INVALID_BARCODES as $barcodeTestSet) {
$barcodeType = $this->getBarcodeType($barcodeTestSet['type']);

foreach ($barcodeTestSet['barcodes'] as $invalidBarcode) {
try {
$barcodeType->getBarcodeData($invalidBarcode)->getBarcode();
} catch (BarcodeException $exception) {
$this->assertInstanceOf(InvalidCheckDigitException::class, $exception);
continue;
}

$this->assertTrue(false, sprintf('Exception was not thrown for barcode "%s".', $invalidBarcode));
}
}
}


private function getBarcodeType(string $typeClass): TypeInterface
{
return new $typeClass;
}
}

0 comments on commit e6059cc

Please sign in to comment.