@@ -34,6 +34,74 @@ public function getBarcodeData(string $code): Barcode
34
34
35
35
$ dataLength = $ length - 1 ;
36
36
37
+ // Convert proper UPC-E codes into UPC-A codes.
38
+ if ($ this ->upce ) {
39
+ $ strLen = strlen ($ code );
40
+
41
+ if ($ strLen === 8 ) {
42
+ // Parity and checksum digits are provided. Store them for later usage.
43
+ $ checksumDigit = $ code [7 ];
44
+ $ parityDigit = $ code [0 ];
45
+ $ code = substr ($ code , 1 , 6 );
46
+ $ strLen -= 2 ;
47
+ }
48
+ if ($ strLen === 7 ) {
49
+ // Either parity or checksum digit is provided.
50
+ if (($ code [0 ] === '0 ' ) || ($ code [0 ] === '1 ' )) {
51
+ // Assume parity digit.
52
+ $ parityDigit = $ code [0 ];
53
+ $ code = substr ($ code , 1 , 6 );
54
+ } else {
55
+ // Assume checksum digit.
56
+ $ checksumDigit = $ code [6 ];
57
+ $ code = substr ($ code , 0 , 6 );
58
+ }
59
+
60
+ --$ strLen ;
61
+ }
62
+ if ($ strLen === 6 ) {
63
+ // Store original UPC-E code for later usage.
64
+ $ upce_code = $ code ; // Neither parity digit nor checksum digit are printed in UPC-E barcode.
65
+
66
+ // Convert UPC-E code into UPC-A code.
67
+ $ conversionData = array (
68
+ '0 ' => array (2 , '00000 ' ),
69
+ '1 ' => array (2 , '10000 ' ),
70
+ '2 ' => array (2 , '20000 ' ),
71
+ '3 ' => array (3 , '00000 ' ),
72
+ '4 ' => array (4 , '00000 ' ),
73
+ '5 ' => array (5 , '00005 ' ),
74
+ '6 ' => array (5 , '00006 ' ),
75
+ '7 ' => array (5 , '00007 ' ),
76
+ '8 ' => array (5 , '00008 ' ),
77
+ '9 ' => array (5 , '00009 ' )
78
+ );
79
+ $ lastUpcEDigit = $ code [5 ];
80
+
81
+ if (!isset ($ conversionData [$ lastUpcEDigit ])) {
82
+ throw new InvalidCharacterException ('Char ' . $ lastUpcEDigit . ' not allowed ' );
83
+ }
84
+
85
+ $ conversionData = $ conversionData [$ lastUpcEDigit ];
86
+ $ code = substr ($ upce_code , 0 , $ conversionData [0 ]); // Add all Xs.
87
+ $ code .= $ conversionData [1 ]; // Add constant number.
88
+ $ code .= substr ($ upce_code , $ conversionData [0 ], 5 - $ conversionData [0 ]); // Add all Ns.
89
+
90
+ // Add parity digit.
91
+ if (!isset ($ parityDigit )) {
92
+ // Provide '0' as default parity digit.
93
+ $ parityDigit = '0 ' ;
94
+ }
95
+
96
+ $ code = $ parityDigit . $ code ;
97
+
98
+ // Add checksum digit.
99
+ if (isset ($ checksumDigit )) {
100
+ $ code .= $ checksumDigit ;
101
+ } // else { The checksum digit will be calculated and added, later. }
102
+ }
103
+ }
104
+
37
105
// Add zero padding in front
38
106
$ code = str_pad ($ code , $ dataLength , '0 ' , STR_PAD_LEFT );
39
107
@@ -44,16 +112,27 @@ public function getBarcodeData(string $code): Barcode
44
112
} elseif ($ checksumDigit !== intval ($ code [$ dataLength ])) {
45
113
// If length of given barcode is same as final length, barcode is including checksum
46
114
// Make sure that checksum is the same as we calculated
47
- throw new InvalidCheckDigitException ();
115
+ if ($ this ->upce && isset ($ upce_code )) {
116
+ // It's possible that parity digit was not provided and the assumed '0' is wrong. Try again with '1'.
117
+ $ parityDigit = '1 ' ;
118
+ $ code [0 ] = $ parityDigit ;
119
+ $ checksumDigit = $ this ->calculateChecksumDigit ($ code );
120
+
121
+ if ($ checksumDigit !== intval ($ code [$ dataLength ])) {
122
+ throw new InvalidCheckDigitException ();
123
+ }
124
+ } else {
125
+ throw new InvalidCheckDigitException ();
126
+ }
48
127
}
49
128
50
129
if ($ this ->upca || $ this ->upce ) {
51
130
$ code = '0 ' . $ code ;
52
131
++$ length ;
53
132
}
54
-
55
- if ($ this ->upce ) {
56
- // convert UPC-A to UPC-E
133
+
134
+ if ($ this ->upce && ! isset ( $ upce_code ) ) {
135
+ // UPC-A code shall be printed as UPC-E code. Convert UPC-A into UPC-E:
57
136
$ tmp = substr ($ code , 4 , 3 );
58
137
if (($ tmp == '000 ' ) OR ($ tmp == '100 ' ) OR ($ tmp == '200 ' )) {
59
138
// manufacturer code ends in 000, 100, or 200
0 commit comments