|
3 | 3 | namespace Picqer\Barcode\Types; |
4 | 4 |
|
5 | 5 | use Picqer\Barcode\Barcode; |
| 6 | +use Picqer\Barcode\Exceptions\InvalidCharacterException; |
| 7 | +use Picqer\Barcode\Exceptions\InvalidCheckDigitException; |
| 8 | +use Picqer\Barcode\Exceptions\InvalidLengthException; |
6 | 9 |
|
7 | 10 | /* |
8 | 11 | * CODE 32 - italian pharmaceutical |
@@ -47,14 +50,65 @@ class TypeCode32 extends TypeCode39 |
47 | 50 |
|
48 | 51 | public function getBarcodeData(string $code): Barcode |
49 | 52 | { |
50 | | - $code39 = ''; |
| 53 | + // Validate code 32. |
| 54 | + $stringLength = strlen($code); |
| 55 | + |
| 56 | + for ($i = 0; $i < $stringLength; ++$i) { |
| 57 | + if (!is_numeric($code[$i])) { |
| 58 | + throw new InvalidCharacterException('Character "' . $code[$i] . '" is not supported.'); |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + // Prepare code 32. |
| 63 | + $code = str_pad($code, 8, '0', STR_PAD_LEFT); |
| 64 | + $checksumDigit = $this->checksum_code32(substr($code, 0, 8)); |
| 65 | + $stringLength = max($stringLength, 8); |
| 66 | + |
| 67 | + if ($stringLength === 8) { |
| 68 | + $code .= $checksumDigit; |
| 69 | + ++$stringLength; |
| 70 | + } |
| 71 | + if ($stringLength !== 9) { |
| 72 | + throw new InvalidLengthException('Only a code consisting of no more than 9 numbers is supported.'); |
| 73 | + } |
| 74 | + if ($code[8] !== $checksumDigit) { |
| 75 | + throw new InvalidCheckDigitException('Provided checksum digit is wrong for provided code.'); |
| 76 | + } |
| 77 | + |
| 78 | + // Convert code 32 into code 39. |
| 79 | + $code39 = ''; |
51 | 80 | $codeElab = $code; |
52 | | - |
53 | | - for ($e = 5; $e >= 0; $e--) { |
54 | | - $code39 .= $this->conversionTable32[intval($codeElab / pow(32,$e))]; |
55 | | - $codeElab = intval($codeElab % pow(32,$e)); |
56 | | - } |
57 | | - |
| 81 | + |
| 82 | + for ($e = 5; $e >= 0; --$e) { |
| 83 | + $code39 .= $this->conversionTable32[intval($codeElab / pow(32, $e))]; |
| 84 | + $codeElab = $codeElab % pow(32, $e); |
| 85 | + } |
| 86 | + |
| 87 | + // Return barcode data for code 39. |
58 | 88 | return parent::getBarcodeData($code39); |
59 | | - } |
| 89 | + } |
| 90 | + |
| 91 | + |
| 92 | + /** |
| 93 | + * Calculate CODE 32 checksum (modulo 10). |
| 94 | + * |
| 95 | + * @param string $code code to represent. |
| 96 | + * @return string char checksum. |
| 97 | + * @protected |
| 98 | + */ |
| 99 | + protected function checksum_code32(string $code): string |
| 100 | + { |
| 101 | + $s = 0; |
| 102 | + |
| 103 | + foreach (str_split($code) as $i => $c) { |
| 104 | + if (0 === $i % 2) { |
| 105 | + $s += (int)$c; |
| 106 | + } else { |
| 107 | + $c = 2 * (int)$c; |
| 108 | + $s += (int)floor($c / 10) + ($c % 10); |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + return (string)$s % 10; |
| 113 | + } |
60 | 114 | } |
0 commit comments