TCPDFBarcode   D
last analyzed

Complexity

Total Complexity 218

Size/Duplication

Total Lines 1911
Duplicated Lines 9.16 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 175
loc 1911
rs 4.4102
c 0
b 0
f 0
wmc 218
lcom 1
cbo 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getBarcodeArray() 0 3 1
D setBarcode() 0 126 30
C barcode_code39() 0 87 8
B encode_code39_ext() 6 44 3
A checksum_code39() 0 15 2
C barcode_code93() 24 121 7
B checksum_code93() 16 38 5
A checksum_s25() 0 16 4
C barcode_msi() 8 49 7
B barcode_s25() 8 33 5
B binseq_to_array() 14 20 6
B barcode_i25() 0 55 9
D barcode_c128() 0 185 16
F barcode_eanupc() 17 183 27
B barcode_eanext() 4 66 4
B barcode_postnet() 0 63 6
C barcode_rms4cc() 0 143 11
B barcode_codabar() 17 48 5
D barcode_code11() 43 84 13
A barcode_pharmacode() 0 18 3
C barcode_pharmacode2t() 0 52 9
F barcode_imb() 0 117 16
A dec_to_hex() 0 17 4
A hex_to_dec() 0 10 2
B imb_crc11fcs() 18 29 6
A imb_reverse_us() 0 9 2
B imb_tables() 0 30 6

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like TCPDFBarcode often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TCPDFBarcode, and based on these observations, apply Extract Interface, too.

1
<?php
2
//============================================================+
3
// File name   : barcodes.php
4
// Begin       : 2008-06-09
5
// Last Update : 2009-08-26
6
// Version     : 1.0.009
7
// License     : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
8
// 	----------------------------------------------------------------------------
9
//  Copyright (C) 2008-2009 Nicola Asuni - Tecnick.com S.r.l.
10
// 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
11
// 	This program is free software: you can redistribute it and/or modify
12
// 	it under the terms of the GNU Lesser General Public License as published by
13
// 	the Free Software Foundation, either version 2.1 of the License, or
14
// 	(at your option) any later version.
15
// 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
16
// 	This program is distributed in the hope that it will be useful,
17
// 	but WITHOUT ANY WARRANTY; without even the implied warranty of
18
// 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
// 	GNU Lesser General Public License for more details.
20
// 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
21
// 	You should have received a copy of the GNU Lesser General Public License
22
// 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
// 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
24
// 	See LICENSE.TXT file for more information.
25
//  ----------------------------------------------------------------------------
26
//
27
// Description : PHP class to creates array representations for 
28
//               common 1D barcodes to be used with TCPDF.
29
//
30
// Author: Nicola Asuni
31
//
32
// (c) Copyright:
33
//               Nicola Asuni
34
//               Tecnick.com S.r.l.
35
//               Via della Pace, 11
36
//               09044 Quartucciu (CA)
37
//               ITALY
38
//               www.tecnick.com
39
//               [email protected]
40
//============================================================+
41
42
/**
43
 * PHP class to creates array representations for common 1D barcodes to be used with TCPDF.
44
 * @package com.tecnick.tcpdf
45
 * @abstract Functions for generating string representation of common 1D barcodes.
46
 * @author Nicola Asuni
47
 * @copyright 2008-2009 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - [email protected]
48
 * @link http://www.tcpdf.org
49
 * @license http://www.gnu.org/copyleft/lesser.html LGPL
50
 * @version 1.0.008
51
 */
52
53
	/**
54
	 * PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br>
55
	 * @name TCPDFBarcode
56
	 * @package com.tecnick.tcpdf
57
	 * @version 1.0.008
58
	 * @author Nicola Asuni
59
	 * @link http://www.tcpdf.org
60
	 * @license http://www.gnu.org/copyleft/lesser.html LGPL
61
	 */
62
class TCPDFBarcode {
63
	
64
	/**
65
	 * @var array representation of barcode.
66
	 * @access protected
67
	 */
68
	protected $barcode_array;
69
		
70
	/**
71
	 * This is the class constructor. 
72
	 * Return an array representations for common 1D barcodes:<ul>
73
	 * <li>$arrcode['code'] code to be printed on text label</li>
74
	 * <li>$arrcode['maxh'] max bar height</li>
75
	 * <li>$arrcode['maxw'] max bar width</li>
76
	 * <li>$arrcode['bcode'][$k] single bar or space in $k position</li>
77
	 * <li>$arrcode['bcode'][$k]['t'] bar type: true = bar, false = space.</li>
78
	 * <li>$arrcode['bcode'][$k]['w'] bar width in units.</li>
79
	 * <li>$arrcode['bcode'][$k]['h'] bar height in units.</li>
80
	 * <li>$arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)</li></ul>
81
	 * @param string $code code to print
82
	 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
83
	 */
84
	public function __construct($code, $type) {
85
		$this->setBarcode($code, $type);
86
	}
87
	
88
	/** 
89
	 * Return an array representations of barcode.
90
	 * @return array
91
	 */
92
	public function getBarcodeArray() {
93
		return $this->barcode_array;
94
	}
95
	
96
	/** 
97
	 * Set the barcode.
98
	 * @param string $code code to print
99
	 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
100
	 * @return array
101
	 */
102
	public function setBarcode($code, $type) {
103
		switch (strtoupper($type)) {
104
			case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
105
				$arrcode = $this->barcode_code39($code, false, false);
106
				break;
107
			}
108
			case 'C39+': { // CODE 39 with checksum
109
				$arrcode = $this->barcode_code39($code, false, true);
110
				break;
111
			}
112
			case 'C39E': { // CODE 39 EXTENDED
113
				$arrcode = $this->barcode_code39($code, true, false);
114
				break;
115
			}
116
			case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
117
				$arrcode = $this->barcode_code39($code, true, true);
118
				break;
119
			}
120
			case 'C93': { // CODE 93 - USS-93
121
				$arrcode = $this->barcode_code93($code);
122
				break;
123
			}
124
			case 'S25': { // Standard 2 of 5
125
				$arrcode = $this->barcode_s25($code, false);
126
				break;
127
			}
128
			case 'S25+': { // Standard 2 of 5 + CHECKSUM
129
				$arrcode = $this->barcode_s25($code, true);
130
				break;
131
			}
132
			case 'I25': { // Interleaved 2 of 5
133
				$arrcode = $this->barcode_i25($code, false);
134
				break;
135
			}
136
			case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
137
				$arrcode = $this->barcode_i25($code, true);
138
				break;
139
			}
140
			case 'C128A': { // CODE 128 A
141
				$arrcode = $this->barcode_c128($code, 'A');
142
				break;
143
			}
144
			case 'C128B': { // CODE 128 B
145
				$arrcode = $this->barcode_c128($code, 'B');
146
				break;
147
			}
148
			case 'C128C': { // CODE 128 C
149
				$arrcode = $this->barcode_c128($code, 'C');
150
				break;
151
			}
152
			case 'EAN2': { // 2-Digits UPC-Based Extention
153
				$arrcode = $this->barcode_eanext($code, 2);
154
				break;
155
			}
156
			case 'EAN5': { // 5-Digits UPC-Based Extention
157
				$arrcode = $this->barcode_eanext($code, 5);
158
				break;
159
			}
160
			case 'EAN8': { // EAN 8
161
				$arrcode = $this->barcode_eanupc($code, 8);
162
				break;
163
			}
164
			case 'EAN13': { // EAN 13
165
				$arrcode = $this->barcode_eanupc($code, 13);
166
				break;
167
			}
168
			case 'UPCA': { // UPC-A
169
				$arrcode = $this->barcode_eanupc($code, 12);
170
				break;
171
			}
172
			case 'UPCE': { // UPC-E
173
				$arrcode = $this->barcode_eanupc($code, 6);
174
				break;
175
			}
176
			case 'MSI': { // MSI (Variation of Plessey code)
177
				$arrcode = $this->barcode_msi($code, false);
178
				break;
179
			}
180
			case 'MSI+': { // MSI + CHECKSUM (modulo 11)
181
				$arrcode = $this->barcode_msi($code, true);
182
				break;
183
			}
184
			case 'POSTNET': { // POSTNET
185
				$arrcode = $this->barcode_postnet($code, false);
186
				break;
187
			}
188
			case 'PLANET': { // PLANET
189
				$arrcode = $this->barcode_postnet($code, true);
190
				break;
191
			}
192
			case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
193
				$arrcode = $this->barcode_rms4cc($code, false);
194
				break;
195
			}
196
			case 'KIX': { // KIX (Klant index - Customer index)
197
				$arrcode = $this->barcode_rms4cc($code, true);
198
				break;
199
			}
200
			case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
201
				$arrcode = $this->barcode_imb($code);
202
				break;
203
			}
204
			case 'CODABAR': { // CODABAR
205
				$arrcode = $this->barcode_codabar($code);
206
				break;
207
			}
208
			case 'CODE11': { // CODE 11
209
				$arrcode = $this->barcode_code11($code);
210
				break;
211
			}
212
			case 'PHARMA': { // PHARMACODE
213
				$arrcode = $this->barcode_pharmacode($code);
214
				break;
215
			}
216
			case 'PHARMA2T': { // PHARMACODE TWO-TRACKS
217
				$arrcode = $this->barcode_pharmacode2t($code);
218
				break;
219
			}
220
			default: {
221
				$this->barcode_array = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type array of property $barcode_array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
222
				$arrcode = false;
223
				break;
224
			}
225
		}
226
		$this->barcode_array = $arrcode;
227
	}
228
	
229
	/**
230
	 * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
231
	 * General-purpose code in very wide use world-wide
232
	 * @param string $code code to represent.
233
	 * @param boolean $checksum if true add a checksum to the code
234
	 * @return array barcode representation.
235
	 * @access protected
236
	 */
237
	protected function barcode_code39($code, $extended = false, $checksum = false) {
238
		$chr['0'] = '111221211';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$chr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $chr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
239
		$chr['1'] = '211211112';
240
		$chr['2'] = '112211112';
241
		$chr['3'] = '212211111';
242
		$chr['4'] = '111221112';
243
		$chr['5'] = '211221111';
244
		$chr['6'] = '112221111';
245
		$chr['7'] = '111211212';
246
		$chr['8'] = '211211211';
247
		$chr['9'] = '112211211';
248
		$chr['A'] = '211112112';
249
		$chr['B'] = '112112112';
250
		$chr['C'] = '212112111';
251
		$chr['D'] = '111122112';
252
		$chr['E'] = '211122111';
253
		$chr['F'] = '112122111';
254
		$chr['G'] = '111112212';
255
		$chr['H'] = '211112211';
256
		$chr['I'] = '112112211';
257
		$chr['J'] = '111122211';
258
		$chr['K'] = '211111122';
259
		$chr['L'] = '112111122';
260
		$chr['M'] = '212111121';
261
		$chr['N'] = '111121122';
262
		$chr['O'] = '211121121';
263
		$chr['P'] = '112121121';
264
		$chr['Q'] = '111111222';
265
		$chr['R'] = '211111221';
266
		$chr['S'] = '112111221';
267
		$chr['T'] = '111121221';
268
		$chr['U'] = '221111112';
269
		$chr['V'] = '122111112';
270
		$chr['W'] = '222111111';
271
		$chr['X'] = '121121112';
272
		$chr['Y'] = '221121111';
273
		$chr['Z'] = '122121111';
274
		$chr['-'] = '121111212';
275
		$chr['.'] = '221111211';
276
		$chr[' '] = '122111211';
277
		$chr['$'] = '121212111';
278
		$chr['/'] = '121211121';
279
		$chr['+'] = '121112121';
280
		$chr['%'] = '111212121';
281
		$chr['*'] = '121121211';
282
		
283
		$code = strtoupper($code);
284
		if ($extended) {
285
			// extended mode
286
			$code = $this->encode_code39_ext($code);
287
		}
288
		if ($code === false) {
289
			return false;
290
		}
291
		if ($checksum) {
292
			// checksum
293
			$code .= $this->checksum_code39($code);
294
		}
295
		// add start and stop codes
296
		$code = '*'.$code.'*';
297
		
298
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
299
		$k = 0;
300
		$clen = strlen($code);
301
		for ($i = 0; $i < $clen; ++$i) {
302
			$char = $code{$i};
303
			if ( ! isset($chr[$char])) {
304
				// invalid character
305
				return false;
306
			}
307
			for ($j = 0; $j < 9; ++$j) {
308
				if (($j % 2) == 0) {
309
					$t = true; // bar
310
				} else {
311
					$t = false; // space
312
				}
313
				$w = $chr[$char]{$j};
314
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
315
				$bararray['maxw'] += $w;
316
				++$k;
317
			}
318
			$bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
319
			$bararray['maxw'] += 1;
320
			++$k;
321
		}
322
		return $bararray;
323
	}
324
	
325
	/**
326
	 * Encode a string to be used for CODE 39 Extended mode.
327
	 * @param string $code code to represent.
328
	 * @return false|string string.
329
	 * @access protected
330
	 */
331
	protected function encode_code39_ext($code) {
332
		$encode = array(
333
			chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
334
			chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
335
			chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
336
			chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
337
			chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
338
			chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
339
			chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
340
			chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
341
			chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
342
			chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
343
			chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
344
			chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
345
			chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
346
			chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
347
			chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
348
			chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
349
			chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
350
			chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
351
			chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
352
			chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
353
			chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
354
			chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
355
			chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
356
			chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
357
			chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
358
			chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
359
			chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
360
			chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
361
			chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
362
			chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
363
			chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
364
			chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
365
		$code_ext = '';
366
		$clen = strlen($code);
367 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
368
			if (ord($code{$i}) > 127) {
369
				return false;
370
			}
371
			$code_ext .= $encode[$code{$i}];
372
		}
373
		return $code_ext;
374
	}
375
	
376
	/**
377
	 * Calculate CODE 39 checksum (modulo 43).
378
	 * @param string $code code to represent.
379
	 * @return string checksum.
380
	 * @access protected
381
	 */
382
	protected function checksum_code39($code) {
383
		$chars = array(
384
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
385
			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
386
			'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
387
			'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
388
		$sum = 0;
389
		$clen = strlen($code);
390
		for ($i = 0; $i < $clen; ++$i) {
391
			$k = array_keys($chars, $code{$i});
392
			$sum += $k[0];
393
		}
394
		$j = ($sum % 43);
395
		return $chars[$j];
396
	}
397
	
398
	/**
399
	 * CODE 93 - USS-93
400
	 * Compact code similar to Code 39
401
	 * @param string $code code to represent.
402
	 * @return array barcode representation.
403
	 * @access protected
404
	 */
405
	protected function barcode_code93($code) {
406
		$chr['0'] = '131112';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$chr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $chr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
407
		$chr['1'] = '111213';
408
		$chr['2'] = '111312';
409
		$chr['3'] = '111411';
410
		$chr['4'] = '121113';
411
		$chr['5'] = '121212';
412
		$chr['6'] = '121311';
413
		$chr['7'] = '111114';
414
		$chr['8'] = '131211';
415
		$chr['9'] = '141111';
416
		$chr['A'] = '211113';
417
		$chr['B'] = '211212';
418
		$chr['C'] = '211311';
419
		$chr['D'] = '221112';
420
		$chr['E'] = '221211';
421
		$chr['F'] = '231111';
422
		$chr['G'] = '112113';
423
		$chr['H'] = '112212';
424
		$chr['I'] = '112311';
425
		$chr['J'] = '122112';
426
		$chr['K'] = '132111';
427
		$chr['L'] = '111123';
428
		$chr['M'] = '111222';
429
		$chr['N'] = '111321';
430
		$chr['O'] = '121122';
431
		$chr['P'] = '131121';
432
		$chr['Q'] = '212112';
433
		$chr['R'] = '212211';
434
		$chr['S'] = '211122';
435
		$chr['T'] = '211221';
436
		$chr['U'] = '221121';
437
		$chr['V'] = '222111';
438
		$chr['W'] = '112122';
439
		$chr['X'] = '112221';
440
		$chr['Y'] = '122121';
441
		$chr['Z'] = '123111';
442
		$chr['-'] = '121131';
443
		$chr['.'] = '311112';
444
		$chr[' '] = '311211';
445
		$chr['$'] = '321111';
446
		$chr['/'] = '112131';
447
		$chr['+'] = '113121';
448
		$chr['%'] = '211131';
449
		$chr[128] = '121221'; // ($)
450
		$chr[129] = '311121'; // (/)
451
		$chr[130] = '122211'; // (+)
452
		$chr[131] = '312111'; // (%)
453
		$chr['*'] = '111141';
454
		$code = strtoupper($code);
455
		$encode = array(
456
			chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
457
			chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
458
			chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
459
			chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
460
			chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
461
			chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
462
			chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
463
			chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
464
			chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
465
			chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
466
			chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
467
			chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
468
			chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
469
			chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
470
			chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
471
			chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
472
			chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
473
			chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
474
			chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
475
			chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
476
			chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
477
			chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
478
			chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
479
			chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
480
			chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
481
			chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
482
			chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
483
			chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
484
			chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
485
			chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
486
			chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
487
			chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
488
		$code_ext = '';
489
		$clen = strlen($code);
490 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
491
			if (ord($code{$i}) > 127) {
492
				return false;
493
			}
494
			$code_ext .= $encode[$code{$i}];
495
		}
496
		// checksum
497
		$code .= $this->checksum_code93($code);
498
		// add start and stop codes
499
		$code = '*'.$code.'*';
500
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
501
		$k = 0;
502
		$clen = strlen($code);
503 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
504
			$char = $code{$i};
505
			if ( ! isset($chr[$char])) {
506
				// invalid character
507
				return false;
508
			}
509
			for ($j = 0; $j < 6; ++$j) {
510
				if (($j % 2) == 0) {
511
					$t = true; // bar
512
				} else {
513
					$t = false; // space
514
				}
515
				$w = $chr[$char]{$j};
516
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
517
				$bararray['maxw'] += $w;
518
				++$k;
519
			}
520
		}
521
		$bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
522
		$bararray['maxw'] += 1;
523
		++$k;		
524
		return $bararray;
525
	}
526
	
527
	/**
528
	 * Calculate CODE 93 checksum (modulo 47).
529
	 * @param string $code code to represent.
530
	 * @return string checksum code.
531
	 * @access protected
532
	 */
533
	protected function checksum_code93($code) {
534
		$chars = array(
535
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
536
			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
537
			'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
538
			'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
539
		// translate special characters
540
		$code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%');	
541
		$len = strlen($code);
542
		// calculate check digit C
543
		$p = 1;
544
		$check = 0;
545 View Code Duplication
		for ($i = ($len - 1); $i >= 0; --$i) {
546
			$k = array_keys($chars, $code{$i});
547
			$check += ($k[0] * $p);
548
			++$p;
549
			if ($p > 20) {
550
				$p = 1;
551
			}
552
		}
553
		$check %= 47;
554
		$c = $chars[$check];
555
		$code .= $c;
556
		// calculate check digit K
557
		$p = 1;
558
		$check = 0;
559 View Code Duplication
		for ($i = $len; $i >= 0; --$i) {
560
			$k = array_keys($chars, $code{$i});
561
			$check += ($k[0] * $p);
562
			++$p;
563
			if ($p > 15) {
564
				$p = 1;
565
			}
566
		}
567
		$check %= 47;
568
		$k = $chars[$check];
569
		return $c.$k;
570
	}
571
	
572
	/**
573
	 * Checksum for standard 2 of 5 barcodes.
574
	 * @param string $code code to process.
575
	 * @return int checksum.
576
	 * @access protected
577
	 */
578
	protected function checksum_s25($code) {
579
		$len = strlen($code);
580
		$sum = 0;
581
		for ($i = 0; $i < $len; $i += 2) {
582
			$sum += $code{$i};
583
		}
584
		$sum *= 3;
585
		for ($i = 1; $i < $len; $i += 2) {
586
			$sum += ($code{$i});
587
		}
588
		$r = $sum % 10;
589
		if ($r > 0) {
590
			$r = (10 - $r);
591
		}
592
		return $r;
593
	}
594
	
595
	/**
596
	 * MSI.
597
	 * Variation of Plessey code, with similar applications 
598
	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
599
	 * @param string $code code to represent.
600
	 * @param boolean $checksum if true add a checksum to the code (modulo 11)
601
	 * @return array barcode representation.
602
	 * @access protected
603
	 */
604
	protected function barcode_msi($code, $checksum = false) {
605
		$chr['0'] = '100100100100';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$chr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $chr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
606
		$chr['1'] = '100100100110';
607
		$chr['2'] = '100100110100';
608
		$chr['3'] = '100100110110';
609
		$chr['4'] = '100110100100';
610
		$chr['5'] = '100110100110';
611
		$chr['6'] = '100110110100';
612
		$chr['7'] = '100110110110';
613
		$chr['8'] = '110100100100';
614
		$chr['9'] = '110100100110';
615
		$chr['A'] = '110100110100';
616
		$chr['B'] = '110100110110';
617
		$chr['C'] = '110110100100';
618
		$chr['D'] = '110110100110';
619
		$chr['E'] = '110110110100';
620
		$chr['F'] = '110110110110';
621
		if ($checksum) {
622
			// add checksum
623
			$clen = strlen($code);
624
			$p = 2;
625
			$check = 0;
626
			for ($i = ($clen - 1); $i >= 0; --$i) {
627
				$check += (hexdec($code{$i}) * $p);
628
				++$p;
629
				if ($p > 7) {
630
					$p = 2;
631
				}
632
			}
633
			$check %= 11;
634
			if ($check > 0) {
635
				$check = 11 - $check;
636
			}
637
			$code .= $check;
638
		}
639
		$seq = '110'; // left guard
640
		$clen = strlen($code);
641 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
642
			$digit = $code{$i};
643
			if ( ! isset($chr[$digit])) {
644
				// invalid character
645
				return false;
646
			}
647
			$seq .= $chr[$digit];
648
		}		
649
		$seq .= '1001'; // right guard
650
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
651
		return $this->binseq_to_array($seq, $bararray);
652
	}
653
	
654
	/**
655
	 * Standard 2 of 5 barcodes.
656
	 * Used in airline ticket marking, photofinishing
657
	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
658
	 * @param string $code code to represent.
659
	 * @param boolean $checksum if true add a checksum to the code
660
	 * @return array barcode representation.
661
	 * @access protected
662
	 */
663
	protected function barcode_s25($code, $checksum = false) {
664
		$chr['0'] = '10101110111010';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$chr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $chr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
665
		$chr['1'] = '11101010101110';
666
		$chr['2'] = '10111010101110';
667
		$chr['3'] = '11101110101010';
668
		$chr['4'] = '10101110101110';
669
		$chr['5'] = '11101011101010';
670
		$chr['6'] = '10111011101010';
671
		$chr['7'] = '10101011101110';
672
		$chr['8'] = '10101110111010';
673
		$chr['9'] = '10111010111010';
674
		if ($checksum) {
675
			// add checksum
676
			$code .= $this->checksum_s25($code);
677
		}
678
		if ((strlen($code) % 2) != 0) {
679
			// add leading zero if code-length is odd
680
			$code = '0'.$code;
681
		}
682
		$seq = '11011010';
683
		$clen = strlen($code);
684 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
685
			$digit = $code{$i};
686
			if ( ! isset($chr[$digit])) {
687
				// invalid character
688
				return false;
689
			}
690
			$seq .= $chr[$digit];
691
		}		
692
		$seq .= '1101011';
693
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
694
		return $this->binseq_to_array($seq, $bararray);
695
	}
696
	
697
	/**
698
	 * Convert binary barcode sequence to TCPDF barcode array
699
	 * @param string $seq barcode as binary sequence
700
	 * òparam array $bararray TCPDF barcode array to fill up
701
	 * @return array barcode representation.
702
	 * @access protected
703
	 */
704
	protected function binseq_to_array($seq, $bararray) {
705
		$len = strlen($seq);
706
		$w = 0;
707
		$k = 0;
708 View Code Duplication
		for ($i = 0; $i < $len; ++$i) {
709
			$w += 1;
710
			if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
711
				if ($seq{$i} == '1') {
712
					$t = true; // bar
713
				} else {
714
					$t = false; // space
715
				}
716
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
717
				$bararray['maxw'] += $w;
718
				++$k;
719
				$w = 0;
720
			}
721
		}
722
		return $bararray;
723
	}
724
	
725
	/**
726
	 * Interleaved 2 of 5 barcodes.
727
	 * Compact numeric code, widely used in industry, air cargo
728
	 * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
729
	 * @param string $code code to represent.
730
	 * @param boolean $checksum if true add a checksum to the code
731
	 * @return array barcode representation.
732
	 * @access protected
733
	 */
734
	protected function barcode_i25($code, $checksum = false) {
735
		$chr['0'] = '11221';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$chr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $chr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
736
		$chr['1'] = '21112';
737
		$chr['2'] = '12112';
738
		$chr['3'] = '22111';
739
		$chr['4'] = '11212';
740
		$chr['5'] = '21211';
741
		$chr['6'] = '12211';
742
		$chr['7'] = '11122';
743
		$chr['8'] = '21121';
744
		$chr['9'] = '12121';
745
		$chr['A'] = '11';
746
		$chr['Z'] = '21';
747
		if ($checksum) {
748
			// add checksum
749
			$code .= $this->checksum_s25($code);
750
		}
751
		if ((strlen($code) % 2) != 0) {
752
			// add leading zero if code-length is odd
753
			$code = '0'.$code;
754
		}
755
		// add start and stop codes
756
		$code = 'AA'.strtolower($code).'ZA';
757
			
758
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
759
		$k = 0;
760
		$clen = strlen($code);
761
		for ($i = 0; $i < $clen; $i = ($i + 2)) {
762
			$char_bar = $code{$i};
763
			$char_space = $code{$i + 1};
764
			if (( ! isset($chr[$char_bar])) OR ( ! isset($chr[$char_space]))) {
765
				// invalid character
766
				return false;
767
			}
768
			// create a bar-space sequence
769
			$seq = '';
770
			$chrlen = strlen($chr[$char_bar]);
771
			for ($s = 0; $s < $chrlen; $s++) {
772
				$seq .= $chr[$char_bar]{$s}.$chr[$char_space]{$s};
773
			}
774
			$seqlen = strlen($seq);
775
			for ($j = 0; $j < $seqlen; ++$j) {
776
				if (($j % 2) == 0) {
777
					$t = true; // bar
778
				} else {
779
					$t = false; // space
780
				}
781
				$w = $seq{$j};
782
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
783
				$bararray['maxw'] += $w;
784
				++$k;
785
			}
786
		}
787
		return $bararray;
788
	}
789
	
790
	/**
791
	 * C128 barcodes. 
792
	 * Very capable code, excellent density, high reliability; in very wide use world-wide
793
	 * @param string $code code to represent.
794
	 * @param string $type barcode type: A, B or C
795
	 * @return array barcode representation.
796
	 * @access protected
797
	 */
798
	protected function barcode_c128($code, $type = 'B') {
799
		$chr = array(
800
			'212222', /* 00 */
801
			'222122', /* 01 */
802
			'222221', /* 02 */
803
			'121223', /* 03 */
804
			'121322', /* 04 */
805
			'131222', /* 05 */
806
			'122213', /* 06 */
807
			'122312', /* 07 */
808
			'132212', /* 08 */
809
			'221213', /* 09 */
810
			'221312', /* 10 */
811
			'231212', /* 11 */
812
			'112232', /* 12 */
813
			'122132', /* 13 */
814
			'122231', /* 14 */
815
			'113222', /* 15 */
816
			'123122', /* 16 */
817
			'123221', /* 17 */
818
			'223211', /* 18 */
819
			'221132', /* 19 */
820
			'221231', /* 20 */
821
			'213212', /* 21 */
822
			'223112', /* 22 */
823
			'312131', /* 23 */
824
			'311222', /* 24 */
825
			'321122', /* 25 */
826
			'321221', /* 26 */
827
			'312212', /* 27 */
828
			'322112', /* 28 */
829
			'322211', /* 29 */
830
			'212123', /* 30 */
831
			'212321', /* 31 */
832
			'232121', /* 32 */
833
			'111323', /* 33 */
834
			'131123', /* 34 */
835
			'131321', /* 35 */
836
			'112313', /* 36 */
837
			'132113', /* 37 */
838
			'132311', /* 38 */
839
			'211313', /* 39 */
840
			'231113', /* 40 */
841
			'231311', /* 41 */
842
			'112133', /* 42 */
843
			'112331', /* 43 */
844
			'132131', /* 44 */
845
			'113123', /* 45 */
846
			'113321', /* 46 */
847
			'133121', /* 47 */
848
			'313121', /* 48 */
849
			'211331', /* 49 */
850
			'231131', /* 50 */
851
			'213113', /* 51 */
852
			'213311', /* 52 */
853
			'213131', /* 53 */
854
			'311123', /* 54 */
855
			'311321', /* 55 */
856
			'331121', /* 56 */
857
			'312113', /* 57 */
858
			'312311', /* 58 */
859
			'332111', /* 59 */
860
			'314111', /* 60 */
861
			'221411', /* 61 */
862
			'431111', /* 62 */
863
			'111224', /* 63 */
864
			'111422', /* 64 */
865
			'121124', /* 65 */
866
			'121421', /* 66 */
867
			'141122', /* 67 */
868
			'141221', /* 68 */
869
			'112214', /* 69 */
870
			'112412', /* 70 */
871
			'122114', /* 71 */
872
			'122411', /* 72 */
873
			'142112', /* 73 */
874
			'142211', /* 74 */
875
			'241211', /* 75 */
876
			'221114', /* 76 */
877
			'413111', /* 77 */
878
			'241112', /* 78 */
879
			'134111', /* 79 */
880
			'111242', /* 80 */
881
			'121142', /* 81 */
882
			'121241', /* 82 */
883
			'114212', /* 83 */
884
			'124112', /* 84 */
885
			'124211', /* 85 */
886
			'411212', /* 86 */
887
			'421112', /* 87 */
888
			'421211', /* 88 */
889
			'212141', /* 89 */
890
			'214121', /* 90 */
891
			'412121', /* 91 */
892
			'111143', /* 92 */
893
			'111341', /* 93 */
894
			'131141', /* 94 */
895
			'114113', /* 95 */
896
			'114311', /* 96 */
897
			'411113', /* 97 */
898
			'411311', /* 98 */
899
			'113141', /* 99 */
900
			'114131', /* 100 */
901
			'311141', /* 101 */
902
			'411131', /* 102 */
903
			'211412', /* 103 START A */
904
			'211214', /* 104 START B  */
905
			'211232', /* 105 START C  */
906
			'233111', /* STOP */
907
			'200000'  /* END */
908
		);
909
		$keys = '';
910
		switch (strtoupper($type)) {
911
			case 'A': {
912
				$startid = 103;
913
				$keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
914
				for ($i = 0; $i < 32; ++$i) {
915
					$keys .= chr($i);
916
				}
917
				break;
918
			}
919
			case 'B': {
920
				$startid = 104;
921
				$keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
922
				break;
923
			}
924
			case 'C': {
925
				$startid = 105;
926
				$keys = '';
927
				if ((strlen($code) % 2) != 0) {
928
					// The length of barcode value must be even ($code). You must pad the number with zeros
929
					return false;
930
				}
931
				for ($i = 0; $i <= 99; ++$i) {
932
					$keys .= chr($i);
933
				}
934
				$new_code = '';
935
				$hclen = (strlen($code) / 2);
936
				for ($i = 0; $i < $hclen; ++$i) {
937
					$new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
938
				}
939
				$code = $new_code;
940
				break;
941
			}
942
			default: {
943
				return false;
944
			}
945
		}
946
		// calculate check character
947
		$sum = $startid;
948
		$clen = strlen($code);
949
		for ($i = 0; $i < $clen; ++$i) {
950
			$sum += (strpos($keys, $code{$i}) * ($i + 1));
951
		}
952
		$check = ($sum % 103);
953
		// add start, check and stop codes
954
		$code = chr($startid).$code.chr($check).chr(106).chr(107);
955
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
956
		$k = 0;
957
		$len = strlen($code);
958
		for ($i = 0; $i < $len; ++$i) {
959
			$ck = strpos($keys, $code{$i});
960
			if (($i == 0) OR ($i > ($len - 4))) {
961
				$char_num = ord($code{$i});
962
				$seq = $chr[$char_num];
963
			} elseif (($ck >= 0) AND isset($chr[$ck])) {
964
					$seq = $chr[$ck];
965
			} else {
966
				// invalid character
967
				return false;
968
			}
969
			for ($j = 0; $j < 6; ++$j) {
970
				if (($j % 2) == 0) {
971
					$t = true; // bar
972
				} else {
973
					$t = false; // space
974
				}
975
				$w = $seq{$j};
976
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
977
				$bararray['maxw'] += $w;
978
				++$k;
979
			}
980
		}
981
		return $bararray;		
982
	}
983
	
984
	/**
985
	 * EAN13 and UPC-A barcodes.
986
	 * EAN13: European Article Numbering international retail product code
987
	 * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
988
	 * UPC-E: Short version of UPC symbol
989
	 * @param string $code code to represent.
990
	 * @param integer $len barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
991
	 * @return array barcode representation.
992
	 * @access protected
993
	 */
994
	protected function barcode_eanupc($code, $len = 13) {
995
		$upce = false;
996
		if ($len == 6) {
997
			$len = 12; // UPC-A
998
			$upce = true; // UPC-E mode
999
		}
1000
		$data_len = $len - 1;
1001
		//Padding
1002
		$code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
1003
		$code_len = strlen($code);
1004
		// calculate check digit
1005
		$sum_a = 0;
1006
		for ($i = 1; $i < $data_len; $i += 2) {
1007
			$sum_a += $code{$i};
1008
		}
1009
		if ($len > 12) {
1010
			$sum_a *= 3;
1011
		}
1012
		$sum_b = 0;
1013
		for ($i = 0; $i < $data_len; $i += 2) {
1014
			$sum_b += ($code{$i});
1015
		}
1016
		if ($len < 13) {
1017
			$sum_b *= 3;
1018
		}
1019
		$r = ($sum_a + $sum_b) % 10;
1020
		if ($r > 0) {
1021
			$r = (10 - $r);
1022
		}
1023
		if ($code_len == $data_len) {
1024
			// add check digit
1025
			$code .= $r;
1026
		} elseif ($r !== intval($code{$data_len})) {
1027
			// wrong checkdigit
1028
			return false;
1029
		}
1030
		if ($len == 12) {
1031
			// UPC-A
1032
			$code = '0'.$code;
1033
			++$len;
1034
		}
1035
		if ($upce) {
1036
			// convert UPC-A to UPC-E
1037
			$tmp = substr($code, 4, 3);
1038
			if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
1039
				// manufacturer code ends in 000, 100, or 200
1040
				$upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
1041
			} else {
1042
				$tmp = substr($code, 5, 2);
1043
				if ($tmp == '00') {
1044
					// manufacturer code ends in 00
1045
					$upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
1046
				} else {
1047
					$tmp = substr($code, 6, 1);
1048
					if ($tmp == '0') {
1049
						// manufacturer code ends in 0
1050
						$upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
1051
					} else {
1052
						// manufacturer code does not end in zero
1053
						$upce_code = substr($code, 2, 5).substr($code, 11, 1);
1054
					}
1055
				}
1056
			}
1057
		}
1058
		//Convert digits to bars
1059
		$codes = array(
1060
			'A'=>array( // left odd parity
1061
				'0'=>'0001101',
1062
				'1'=>'0011001',
1063
				'2'=>'0010011',
1064
				'3'=>'0111101',
1065
				'4'=>'0100011',
1066
				'5'=>'0110001',
1067
				'6'=>'0101111',
1068
				'7'=>'0111011',
1069
				'8'=>'0110111',
1070
				'9'=>'0001011'),
1071
			'B'=>array( // left even parity
1072
				'0'=>'0100111',
1073
				'1'=>'0110011',
1074
				'2'=>'0011011',
1075
				'3'=>'0100001',
1076
				'4'=>'0011101',
1077
				'5'=>'0111001',
1078
				'6'=>'0000101',
1079
				'7'=>'0010001',
1080
				'8'=>'0001001',
1081
				'9'=>'0010111'),
1082
			'C'=>array( // right
1083
				'0'=>'1110010',
1084
				'1'=>'1100110',
1085
				'2'=>'1101100',
1086
				'3'=>'1000010',
1087
				'4'=>'1011100',
1088
				'5'=>'1001110',
1089
				'6'=>'1010000',
1090
				'7'=>'1000100',
1091
				'8'=>'1001000',
1092
				'9'=>'1110100')
1093
		);
1094
		$parities = array(
1095
			'0'=>array('A', 'A', 'A', 'A', 'A', 'A'),
1096
			'1'=>array('A', 'A', 'B', 'A', 'B', 'B'),
1097
			'2'=>array('A', 'A', 'B', 'B', 'A', 'B'),
1098
			'3'=>array('A', 'A', 'B', 'B', 'B', 'A'),
1099
			'4'=>array('A', 'B', 'A', 'A', 'B', 'B'),
1100
			'5'=>array('A', 'B', 'B', 'A', 'A', 'B'),
1101
			'6'=>array('A', 'B', 'B', 'B', 'A', 'A'),
1102
			'7'=>array('A', 'B', 'A', 'B', 'A', 'B'),
1103
			'8'=>array('A', 'B', 'A', 'B', 'B', 'A'),
1104
			'9'=>array('A', 'B', 'B', 'A', 'B', 'A')
1105
		);
1106
		$upce_parities = array();
1107
		$upce_parities[0] = array(
1108
			'0'=>array('B', 'B', 'B', 'A', 'A', 'A'),
1109
			'1'=>array('B', 'B', 'A', 'B', 'A', 'A'),
1110
			'2'=>array('B', 'B', 'A', 'A', 'B', 'A'),
1111
			'3'=>array('B', 'B', 'A', 'A', 'A', 'B'),
1112
			'4'=>array('B', 'A', 'B', 'B', 'A', 'A'),
1113
			'5'=>array('B', 'A', 'A', 'B', 'B', 'A'),
1114
			'6'=>array('B', 'A', 'A', 'A', 'B', 'B'),
1115
			'7'=>array('B', 'A', 'B', 'A', 'B', 'A'),
1116
			'8'=>array('B', 'A', 'B', 'A', 'A', 'B'),
1117
			'9'=>array('B', 'A', 'A', 'B', 'A', 'B')
1118
		);
1119
		$upce_parities[1] = array(
1120
			'0'=>array('A', 'A', 'A', 'B', 'B', 'B'),
1121
			'1'=>array('A', 'A', 'B', 'A', 'B', 'B'),
1122
			'2'=>array('A', 'A', 'B', 'B', 'A', 'B'),
1123
			'3'=>array('A', 'A', 'B', 'B', 'B', 'A'),
1124
			'4'=>array('A', 'B', 'A', 'A', 'B', 'B'),
1125
			'5'=>array('A', 'B', 'B', 'A', 'A', 'B'),
1126
			'6'=>array('A', 'B', 'B', 'B', 'A', 'A'),
1127
			'7'=>array('A', 'B', 'A', 'B', 'A', 'B'),
1128
			'8'=>array('A', 'B', 'A', 'B', 'B', 'A'),
1129
			'9'=>array('A', 'B', 'B', 'A', 'B', 'A')
1130
		);
1131
		$k = 0;
1132
		$seq = '101'; // left guard bar
1133
		if ($upce) {
1134
			$bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
0 ignored issues
show
Bug introduced by
The variable $upce_code does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1135
			$p = $upce_parities[$code{1}][$r];
1136
			for ($i = 0; $i < 6; ++$i) {
1137
				$seq .= $codes[$p[$i]][$upce_code{$i}];
1138
			}
1139
			$seq .= '010101'; // right guard bar
1140
		} else {
1141
			$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1142
			$half_len = ceil($len / 2);
1143
			if ($len == 8) {
1144
				for ($i = 0; $i < $half_len; ++$i) {
1145
					$seq .= $codes['A'][$code{$i}];
1146
				}
1147
			} else {
1148
				$p = $parities[$code{0}];
1149 View Code Duplication
				for ($i = 1; $i < $half_len; ++$i) {
1150
					$seq .= $codes[$p[$i - 1]][$code{$i}];
1151
				}
1152
			}
1153
			$seq .= '01010'; // center guard bar
1154
			for ($i = $half_len; $i < $len; ++$i) {
1155
				$seq .= $codes['C'][$code{$i}];
1156
			}
1157
			$seq .= '101'; // right guard bar
1158
		}
1159
		$clen = strlen($seq);
1160
		$w = 0;
1161 View Code Duplication
		for ($i = 0; $i < $clen; ++$i) {
1162
			$w += 1;
1163
			if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
1164
				if ($seq{$i} == '1') {
1165
					$t = true; // bar
1166
				} else {
1167
					$t = false; // space
1168
				}
1169
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1170
				$bararray['maxw'] += $w;
1171
				++$k;
1172
				$w = 0;
1173
			}
1174
		}
1175
		return $bararray;
1176
	}
1177
	
1178
	/**
1179
	 * UPC-Based Extentions
1180
	 * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
1181
	 * 5-Digit Ext.: Used to mark suggested retail price of books
1182
	 * @param string $code code to represent.
1183
	 * @param integer $len barcode type: 2 = 2-Digit, 5 = 5-Digit
1184
	 * @return array barcode representation.
1185
	 * @access protected
1186
	 */
1187
	protected function barcode_eanext($code, $len = 5) {
1188
		//Padding
1189
		$code = str_pad($code, $len, '0', STR_PAD_LEFT);
1190
		// calculate check digit
1191
		if ($len == 2) {
1192
			$r = $code % 4;
1193
		} elseif ($len == 5) {
1194
			$r = (3 * ($code{0} +$code{2} +$code{4})) + (9 * ($code{1} +$code{3}));
1195
			$r %= 10;
1196
		} else {
1197
			return false;
1198
		}
1199
		//Convert digits to bars
1200
		$codes = array(
1201
			'A'=>array( // left odd parity
1202
				'0'=>'0001101',
1203
				'1'=>'0011001',
1204
				'2'=>'0010011',
1205
				'3'=>'0111101',
1206
				'4'=>'0100011',
1207
				'5'=>'0110001',
1208
				'6'=>'0101111',
1209
				'7'=>'0111011',
1210
				'8'=>'0110111',
1211
				'9'=>'0001011'),
1212
			'B'=>array( // left even parity
1213
				'0'=>'0100111',
1214
				'1'=>'0110011',
1215
				'2'=>'0011011',
1216
				'3'=>'0100001',
1217
				'4'=>'0011101',
1218
				'5'=>'0111001',
1219
				'6'=>'0000101',
1220
				'7'=>'0010001',
1221
				'8'=>'0001001',
1222
				'9'=>'0010111')
1223
		);
1224
		$parities = array();
1225
		$parities[2] = array(
1226
			'0'=>array('A', 'A'),
1227
			'1'=>array('A', 'B'),
1228
			'2'=>array('B', 'A'),
1229
			'3'=>array('B', 'B')
1230
		);
1231
		$parities[5] = array(
1232
			'0'=>array('B', 'B', 'A', 'A', 'A'),
1233
			'1'=>array('B', 'A', 'B', 'A', 'A'),
1234
			'2'=>array('B', 'A', 'A', 'B', 'A'),
1235
			'3'=>array('B', 'A', 'A', 'A', 'B'),
1236
			'4'=>array('A', 'B', 'B', 'A', 'A'),
1237
			'5'=>array('A', 'A', 'B', 'B', 'A'),
1238
			'6'=>array('A', 'A', 'A', 'B', 'B'),
1239
			'7'=>array('A', 'B', 'A', 'B', 'A'),
1240
			'8'=>array('A', 'B', 'A', 'A', 'B'),
1241
			'9'=>array('A', 'A', 'B', 'A', 'B')
1242
		);	
1243
		$p = $parities[$len][$r];
1244
		$seq = '1011'; // left guard bar
1245
		$seq .= $codes[$p[0]][$code{0}];
1246 View Code Duplication
		for ($i = 1; $i < $len; ++$i) {
1247
			$seq .= '01'; // separator
1248
			$seq .= $codes[$p[$i]][$code{$i}];
1249
		}
1250
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1251
		return $this->binseq_to_array($seq, $bararray);
1252
	}
1253
	
1254
	/**
1255
	 * POSTNET and PLANET barcodes.
1256
	 * Used by U.S. Postal Service for automated mail sorting
1257
	 * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD.
1258
	 * @param boolean $planet if true print the PLANET barcode, otherwise print POSTNET
1259
	 * @return array barcode representation.
1260
	 * @access protected
1261
	 */
1262
	protected function barcode_postnet($code, $planet = false) {
1263
		// bar lenght
1264
		if ($planet) {
1265
			$barlen = Array(
1266
				0 => Array(1, 1, 2, 2, 2),
1267
				1 => Array(2, 2, 2, 1, 1),
1268
				2 => Array(2, 2, 1, 2, 1),
1269
				3 => Array(2, 2, 1, 1, 2),
1270
				4 => Array(2, 1, 2, 2, 1),
1271
				5 => Array(2, 1, 2, 1, 2),
1272
				6 => Array(2, 1, 1, 2, 2),
1273
				7 => Array(1, 2, 2, 2, 1),
1274
				8 => Array(1, 2, 2, 1, 2),
1275
				9 => Array(1, 2, 1, 2, 2)
1276
			);
1277
		} else {
1278
			$barlen = Array(
1279
				0 => Array(2, 2, 1, 1, 1),
1280
				1 => Array(1, 1, 1, 2, 2),
1281
				2 => Array(1, 1, 2, 1, 2),
1282
				3 => Array(1, 1, 2, 2, 1),
1283
				4 => Array(1, 2, 1, 1, 2),
1284
				5 => Array(1, 2, 1, 2, 1),
1285
				6 => Array(1, 2, 2, 1, 1),
1286
				7 => Array(2, 1, 1, 1, 2),
1287
				8 => Array(2, 1, 1, 2, 1),
1288
				9 => Array(2, 1, 2, 1, 1)
1289
			);
1290
		}
1291
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1292
		$k = 0;
1293
		$code = str_replace('-', '', $code);
1294
		$code = str_replace(' ', '', $code);
1295
		$len = strlen($code);
1296
		// calculate checksum
1297
		$sum = 0;
1298
		for ($i = 0; $i < $len; ++$i) {
1299
			$sum += intval($code{$i});
1300
		}
1301
		$chkd = ($sum % 10);
1302
		if ($chkd > 0) {
1303
			$chkd = (10 - $chkd);
1304
		}
1305
		$code .= $chkd;
1306
		$len = strlen($code);
1307
		// start bar
1308
		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1309
		$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1310
		$bararray['maxw'] += 2;
1311
		for ($i = 0; $i < $len; ++$i) {
1312
			for ($j = 0; $j < 5; ++$j) {
1313
				$h = $barlen[$code{$i}][$j];
1314
				$p = floor(1 / $h);
1315
				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1316
				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1317
				$bararray['maxw'] += 2;
1318
			}
1319
		}
1320
		// end bar
1321
		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1322
		$bararray['maxw'] += 1;
1323
		return $bararray;
1324
	}
1325
	
1326
	/**
1327
	 * RMS4CC - CBC - KIX
1328
	 * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
1329
	 * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
1330
	 * @param string $code code to print
1331
	 * @param boolean $kix if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code.
1332
	 * @return array barcode representation.
1333
	 * @access protected
1334
	 */
1335
	protected function barcode_rms4cc($code, $kix = false) {
1336
		$notkix = ! $kix;
1337
		// bar mode
1338
		// 1 = pos 1, length 2
1339
		// 2 = pos 1, length 3
1340
		// 3 = pos 2, length 1
1341
		// 4 = pos 2, length 2
1342
		$barmode = array(
1343
			'0' => array(3, 3, 2, 2),
1344
			'1' => array(3, 4, 1, 2),
1345
			'2' => array(3, 4, 2, 1),
1346
			'3' => array(4, 3, 1, 2),
1347
			'4' => array(4, 3, 2, 1),
1348
			'5' => array(4, 4, 1, 1),
1349
			'6' => array(3, 1, 4, 2),
1350
			'7' => array(3, 2, 3, 2),
1351
			'8' => array(3, 2, 4, 1),
1352
			'9' => array(4, 1, 3, 2),
1353
			'A' => array(4, 1, 4, 1),
1354
			'B' => array(4, 2, 3, 1),
1355
			'C' => array(3, 1, 2, 4),
1356
			'D' => array(3, 2, 1, 4),
1357
			'E' => array(3, 2, 2, 3),
1358
			'F' => array(4, 1, 1, 4),
1359
			'G' => array(4, 1, 2, 3),
1360
			'H' => array(4, 2, 1, 3),
1361
			'I' => array(1, 3, 4, 2),
1362
			'J' => array(1, 4, 3, 2),
1363
			'K' => array(1, 4, 4, 1),
1364
			'L' => array(2, 3, 3, 2),
1365
			'M' => array(2, 3, 4, 1),
1366
			'N' => array(2, 4, 3, 1),
1367
			'O' => array(1, 3, 2, 4),
1368
			'P' => array(1, 4, 1, 4),
1369
			'Q' => array(1, 4, 2, 3),
1370
			'R' => array(2, 3, 1, 4),
1371
			'S' => array(2, 3, 2, 3),
1372
			'T' => array(2, 4, 1, 3),
1373
			'U' => array(1, 1, 4, 4),
1374
			'V' => array(1, 2, 3, 4),
1375
			'W' => array(1, 2, 4, 3),
1376
			'X' => array(2, 1, 3, 4),
1377
			'Y' => array(2, 1, 4, 3),
1378
			'Z' => array(2, 2, 3, 3)		
1379
		);
1380
		$code = strtoupper($code);
1381
		$len = strlen($code);
1382
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
1383
		if ($notkix) {
1384
			// table for checksum calculation (row,col)
1385
			$checktable = array(
1386
				'0' => array(1, 1),
1387
				'1' => array(1, 2),
1388
				'2' => array(1, 3),
1389
				'3' => array(1, 4),
1390
				'4' => array(1, 5),
1391
				'5' => array(1, 0),
1392
				'6' => array(2, 1),
1393
				'7' => array(2, 2),
1394
				'8' => array(2, 3),
1395
				'9' => array(2, 4),
1396
				'A' => array(2, 5),
1397
				'B' => array(2, 0),
1398
				'C' => array(3, 1),
1399
				'D' => array(3, 2),
1400
				'E' => array(3, 3),
1401
				'F' => array(3, 4),
1402
				'G' => array(3, 5),
1403
				'H' => array(3, 0),
1404
				'I' => array(4, 1),
1405
				'J' => array(4, 2),
1406
				'K' => array(4, 3),
1407
				'L' => array(4, 4),
1408
				'M' => array(4, 5),
1409
				'N' => array(4, 0),
1410
				'O' => array(5, 1),
1411
				'P' => array(5, 2),
1412
				'Q' => array(5, 3),
1413
				'R' => array(5, 4),
1414
				'S' => array(5, 5),
1415
				'T' => array(5, 0),
1416
				'U' => array(0, 1),
1417
				'V' => array(0, 2),
1418
				'W' => array(0, 3),
1419
				'X' => array(0, 4),
1420
				'Y' => array(0, 5),
1421
				'Z' => array(0, 0)
1422
			);
1423
			$row = 0;
1424
			$col = 0;
1425
			for ($i = 0; $i < $len; ++$i) {
1426
				$row += $checktable[$code{$i}][0];
1427
				$col += $checktable[$code{$i}][1];
1428
			}
1429
			$row %= 6;
1430
			$col %= 6;
1431
			$chk = array_keys($checktable, array($row, $col));
1432
			$code .= $chk[0];
1433
			++$len;
1434
		}
1435
		$k = 0;
1436
		if ($notkix) {
1437
			// start bar
1438
			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1439
			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1440
			$bararray['maxw'] += 2;
1441
		}
1442
		for ($i = 0; $i < $len; ++$i) {
1443
			for ($j = 0; $j < 4; ++$j) {
1444
				switch ($barmode[$code{$i}][$j]) {
1445
					case 1: {
1446
						$p = 0;
1447
						$h = 2;
1448
						break;
1449
					}
1450
					case 2: {
1451
						$p = 0;
1452
						$h = 3;
1453
						break;
1454
					}
1455
					case 3: {
1456
						$p = 1;
1457
						$h = 1;
1458
						break;
1459
					}
1460
					case 4: {
1461
						$p = 1;
1462
						$h = 2;
1463
						break;
1464
					}
1465
				}
1466
				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
0 ignored issues
show
Bug introduced by
The variable $h does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $p does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1467
				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1468
				$bararray['maxw'] += 2;
1469
			}
1470
		}
1471
		if ($notkix) {
1472
			// stop bar
1473
			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
1474
			$bararray['maxw'] += 1;
1475
		}
1476
		return $bararray;
1477
	}
1478
	
1479
	/**
1480
	 * CODABAR barcodes.
1481
	 * Older code often used in library systems, sometimes in blood banks
1482
	 * @param string $code code to represent.
1483
	 * @return array barcode representation.
1484
	 * @access protected
1485
	 */
1486
	protected function barcode_codabar($code) {
1487
		$chr = array(
1488
			'0' => '11111221',
1489
			'1' => '11112211',
1490
			'2' => '11121121',
1491
			'3' => '22111111',
1492
			'4' => '11211211',
1493
			'5' => '21111211',
1494
			'6' => '12111121',
1495
			'7' => '12112111',
1496
			'8' => '12211111',
1497
			'9' => '21121111',
1498
			'-' => '11122111',
1499
			'$' => '11221111',
1500
			':' => '21112121',
1501
			'/' => '21211121',
1502
			'.' => '21212111',
1503
			'+' => '11222221',
1504
			'A' => '11221211',
1505
			'B' => '12121121',
1506
			'C' => '11121221',
1507
			'D' => '11122211'
1508
		);
1509
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1510
		$k = 0;
1511
		$w = 0;
1512
		$seq = '';
1513
		$code = 'A'.strtoupper($code).'A';
1514
		$len = strlen($code);
1515 View Code Duplication
		for ($i = 0; $i < $len; ++$i) {
1516
			if ( ! isset($chr[$code{$i}])) {
1517
				return false;
1518
			}
1519
			$seq = $chr[$code{$i}];
1520
			for ($j = 0; $j < 8; ++$j) {
1521
				if (($j % 2) == 0) {
1522
					$t = true; // bar
1523
				} else {
1524
					$t = false; // space
1525
				}
1526
				$w = $seq{$j};
1527
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1528
				$bararray['maxw'] += $w;
1529
				++$k;
1530
			}
1531
		}
1532
		return $bararray;
1533
	}
1534
	
1535
	/**
1536
	 * CODE11 barcodes.
1537
	 * Used primarily for labeling telecommunications equipment
1538
	 * @param string $code code to represent.
1539
	 * @return array barcode representation.
1540
	 * @access protected
1541
	 */
1542
	protected function barcode_code11($code) {
1543
		$chr = array(
1544
			'0' => '111121',
1545
			'1' => '211121',
1546
			'2' => '121121',
1547
			'3' => '221111',
1548
			'4' => '112121',
1549
			'5' => '212111',
1550
			'6' => '122111',
1551
			'7' => '111221',
1552
			'8' => '211211',
1553
			'9' => '211111',
1554
			'-' => '112111',
1555
			'S' => '112211'
1556
		);
1557
		
1558
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1559
		$k = 0;
1560
		$w = 0;
1561
		$seq = '';
1562
		$len = strlen($code);
1563
		// calculate check digit C
1564
		$p = 1;
1565
		$check = 0;
1566 View Code Duplication
		for ($i = ($len - 1); $i >= 0; --$i) {
1567
			$digit = $code{$i};
1568
			if ($digit == '-') {
1569
				$dval = 10;
1570
			} else {
1571
				$dval = intval($digit);
1572
			}
1573
			$check += ($dval * $p);
1574
			++$p;
1575
			if ($p > 10) {
1576
				$p = 1;
1577
			}
1578
		}
1579
		$check %= 11;
1580
		if ($check == 10) {
1581
			$check = '-';
1582
		} 
1583
		$code .= $check;
1584
		if ($len > 10) {
1585
			// calculate check digit K
1586
			$p = 1;
1587
			$check = 0;
1588 View Code Duplication
			for ($i = $len; $i >= 0; --$i) {
1589
				$digit = $code{$i};
1590
				if ($digit == '-') {
1591
					$dval = 10;
1592
				} else {
1593
					$dval = intval($digit);
1594
				}
1595
				$check += ($dval * $p);
1596
				++$p;
1597
				if ($p > 9) {
1598
					$p = 1;
1599
				}
1600
			}
1601
			$check %= 11;
1602
			$code .= $check;
1603
			++$len;
1604
		}
1605
		$code = 'S'.$code.'S';
1606
		$len += 3;
1607 View Code Duplication
		for ($i = 0; $i < $len; ++$i) {
1608
			if ( ! isset($chr[$code{$i}])) {
1609
				return false;
1610
			}
1611
			$seq = $chr[$code{$i}];
1612
			for ($j = 0; $j < 6; ++$j) {
1613
				if (($j % 2) == 0) {
1614
					$t = true; // bar
1615
				} else {
1616
					$t = false; // space
1617
				}
1618
				$w = $seq{$j};
1619
				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1620
				$bararray['maxw'] += $w;
1621
				++$k;
1622
			}
1623
		}
1624
		return $bararray;
1625
	}
1626
	
1627
	/**
1628
	 * Pharmacode
1629
	 * Contains digits (0 to 9)
1630
	 * @param string $code code to represent.
1631
	 * @return array barcode representation.
1632
	 * @access protected
1633
	 */
1634
	protected function barcode_pharmacode($code) {
1635
		$seq = '';
1636
		$code = intval($code);
1637
		while ($code > 0) {
1638
			if (($code % 2) == 0) {
1639
				$seq .= '11100';
1640
				$code -= 2;
1641
			} else {
1642
				$seq .= '100';
1643
				$code -= 1;
1644
			}
1645
			$code /= 2;
1646
		}
1647
		$seq = substr($seq, 0, -2);
1648
		$seq = strrev($seq);
1649
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1650
		return $this->binseq_to_array($seq, $bararray);
1651
	}
1652
	
1653
	/**
1654
	 * Pharmacode two-track
1655
	 * Contains digits (0 to 9)
1656
	 * @param string $code code to represent.
1657
	 * @return array barcode representation.
1658
	 * @access protected
1659
	 */
1660
	protected function barcode_pharmacode2t($code) {
1661
		$seq = '';
1662
		$code = intval($code);
1663
		do {
1664
			switch ($code % 3) {
1665
				case 0: {
1666
					$seq .= '3';
1667
					$code = ($code - 3) / 3;
1668
					break;
1669
				}
1670
				case 1: {
1671
					$seq .= '1';
1672
					$code = ($code - 1) / 3;
1673
					break;
1674
				}
1675
				case 2: {
1676
					$seq .= '2';
1677
					$code = ($code - 2) / 3;
1678
					break;
1679
				}
1680
			}
1681
		} while ($code != 0);
1682
		$seq = strrev($seq);
1683
		$k = 0;
1684
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1685
		$len = strlen($seq);
1686
		for ($i = 0; $i < $len; ++$i) {
1687
			switch ($seq{$i}) {
1688
				case '1': {
1689
					$p = 1;
1690
					$h = 1;
1691
					break;
1692
				}
1693
				case '2': {
1694
					$p = 0;
1695
					$h = 1;
1696
					break;
1697
				}
1698
				case '3': {
1699
					$p = 0;
1700
					$h = 2;
1701
					break;
1702
				}
1703
			}
1704
			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
0 ignored issues
show
Bug introduced by
The variable $h does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $p does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1705
			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1706
			$bararray['maxw'] += 2;
1707
		}
1708
		unset($bararray['bcode'][($k - 1)]);
1709
		--$bararray['maxw'];
1710
		return $bararray;
1711
	}
1712
	
1713
	
1714
	/**
1715
	 * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
1716
	 * (requires PHP bcmath extension) 
1717
	 * Intelligent Mail barcode is a 65-bar code for use on mail in the United States.
1718
	 * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the presort identification that is currently printed in human readable form on the optional endorsement line (OEL) as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999. Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000- 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999,  000000000–999999999, and 00000000000–99999999999.</li></ul>
1719
	 * @param string $code code to print, separate the ZIP (routing code) from the rest using a minus char '-' (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode)
1720
	 * @return array barcode representation.
1721
	 * @access protected
1722
	 */
1723
	protected function barcode_imb($code) {
1724
		$asc_chr = array(4, 0, 2, 6, 3, 5, 1, 9, 8, 7, 1, 2, 0, 6, 4, 8, 2, 9, 5, 3, 0, 1, 3, 7, 4, 6, 8, 9, 2, 0, 5, 1, 9, 4, 3, 8, 6, 7, 1, 2, 4, 3, 9, 5, 7, 8, 3, 0, 2, 1, 4, 0, 9, 1, 7, 0, 2, 4, 6, 3, 7, 1, 9, 5, 8);
1725
		$dsc_chr = array(7, 1, 9, 5, 8, 0, 2, 4, 6, 3, 5, 8, 9, 7, 3, 0, 6, 1, 7, 4, 6, 8, 9, 2, 5, 1, 7, 5, 4, 3, 8, 7, 6, 0, 2, 5, 4, 9, 3, 0, 1, 6, 8, 2, 0, 4, 5, 9, 6, 7, 5, 2, 6, 3, 8, 5, 1, 9, 8, 7, 4, 0, 2, 6, 3);
1726
		$asc_pos = array(3, 0, 8, 11, 1, 12, 8, 11, 10, 6, 4, 12, 2, 7, 9, 6, 7, 9, 2, 8, 4, 0, 12, 7, 10, 9, 0, 7, 10, 5, 7, 9, 6, 8, 2, 12, 1, 4, 2, 0, 1, 5, 4, 6, 12, 1, 0, 9, 4, 7, 5, 10, 2, 6, 9, 11, 2, 12, 6, 7, 5, 11, 0, 3, 2);
1727
		$dsc_pos = array(2, 10, 12, 5, 9, 1, 5, 4, 3, 9, 11, 5, 10, 1, 6, 3, 4, 1, 10, 0, 2, 11, 8, 6, 1, 12, 3, 8, 6, 4, 4, 11, 0, 6, 1, 9, 11, 5, 3, 7, 3, 10, 7, 11, 8, 2, 10, 3, 5, 8, 0, 3, 12, 11, 8, 4, 5, 1, 3, 0, 7, 12, 9, 8, 10);
1728
		$code_arr = explode('-', $code);
1729
		$tracking_number = $code_arr[0];
1730
		if (isset($code_arr[1])) {
1731
			$routing_code = $code_arr[1];
1732
		} else {
1733
			$routing_code = '';
1734
		}
1735
		// Conversion of Routing Code
1736
		switch (strlen($routing_code)) {
1737
			case 0: {
1738
				$binary_code = 0;
1739
				break;
1740
			}
1741
			case 5: {
1742
				$binary_code = bcadd($routing_code, '1');
1743
				break;
1744
			}
1745
			case 9: {
1746
				$binary_code = bcadd($routing_code, '100001');
1747
				break;
1748
			}
1749
			case 11: {
1750
				$binary_code = bcadd($routing_code, '1000100001');
1751
				break;
1752
			}
1753
			default: {
1754
				return false;
1755
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1756
			}
1757
		}
1758
		$binary_code = bcmul($binary_code, 10);
1759
		$binary_code = bcadd($binary_code, $tracking_number{0});
1760
		$binary_code = bcmul($binary_code, 5);
1761
		$binary_code = bcadd($binary_code, $tracking_number{1});
1762
		$binary_code .= substr($tracking_number, 2, 18);
1763
		// convert to hexadecimal
1764
		$binary_code = $this->dec_to_hex($binary_code);
1765
		// pad to get 13 bytes
1766
		$binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
1767
		// convert string to array of bytes
1768
		$binary_code_arr = chunk_split($binary_code, 2, "\r");
1769
		$binary_code_arr = substr($binary_code_arr, 0, -1);
1770
		$binary_code_arr = explode("\r", $binary_code_arr);
1771
		// calculate frame check sequence
1772
		$fcs = $this->imb_crc11fcs($binary_code_arr);
0 ignored issues
show
Documentation introduced by
$binary_code_arr is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1773
		// exclude first 2 bits from first byte
1774
		$first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
1775
		$binary_code_102bit = $first_byte.substr($binary_code, 2);
1776
		// convert binary data to codewords
1777
		$codewords = array();
1778
		$data = $this->hex_to_dec($binary_code_102bit);
1779
		$codewords[0] = bcmod($data, 636) * 2;
1780
		$data = bcdiv($data, 636);
1781
		for ($i = 1; $i < 9; ++$i) {
1782
			$codewords[$i] = bcmod($data, 1365);
1783
			$data = bcdiv($data, 1365);
1784
		}
1785
		$codewords[9] = $data;
1786
		if (($fcs >> 10) == 1) {
1787
			$codewords[9] += 659;
1788
		}
1789
		// generate lookup tables
1790
		$table2of13 = $this->imb_tables(2, 78);
1791
		$table5of13 = $this->imb_tables(5, 1287);
1792
		// convert codewords to characters
1793
		$characters = array();
1794
		$bitmask = 512;
1795
		foreach ($codewords as $k => $val) {
1796
			if ($val <= 1286) {
1797
				$chrcode = $table5of13[$val];
1798
			} else {
1799
				$chrcode = $table2of13[($val - 1287)];
1800
			}
1801
			if (($fcs & $bitmask) > 0) {
1802
				// bitwise invert
1803
				$chrcode = ((~$chrcode) & 8191);
1804
			}
1805
			$characters[] = $chrcode;
1806
			$bitmask /= 2;
1807
		}
1808
		$characters = array_reverse($characters);
1809
		// build bars
1810
		$k = 0;
1811
		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
1812
		for ($i = 0; $i < 65; ++$i) {
1813
			$asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
1814
			$dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
1815
			if ($asc AND $dsc) {
1816
				// full bar (F)
1817
				$p = 0;
1818
				$h = 3;
1819
			} elseif ($asc) {
1820
				// ascender (A)
1821
				$p = 0;
1822
				$h = 2;
1823
			} elseif ($dsc) {
1824
				// descender (D)
1825
				$p = 1;
1826
				$h = 2;
1827
			} else {
1828
				// tracker (T)
1829
				$p = 1;
1830
				$h = 1;
1831
			}
1832
			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1833
			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1834
			$bararray['maxw'] += 2;
1835
		}
1836
		unset($bararray['bcode'][($k - 1)]);
1837
		--$bararray['maxw'];
1838
		return $bararray;
1839
	}
1840
	
1841
	/**
1842
	 * Convert large integer number to hexadecimal representation.
1843
	 * (requires PHP bcmath extension) 
1844
	 * @param string $number number to convert specified as a string
1845
	 * @return string hexadecimal representation
1846
	 */
1847
	public function dec_to_hex($number) {
1848
		$i = 0;
1849
		$hex = array();
1850
		if ($number == 0) {
1851
			return '00';
1852
		}
1853
		while ($number > 0) {
1854
			if ($number == 0) {
1855
				array_push($hex, '0');
1856
			} else {
1857
				array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
1858
				$number = bcdiv($number, '16', 0);
1859
			}
1860
		}
1861
		$hex = array_reverse($hex);
1862
		return implode($hex);
1863
	}
1864
	
1865
	/**
1866
	 * Convert large hexadecimal number to decimal representation (string).
1867
	 * (requires PHP bcmath extension) 
1868
	 * @param string $hex hexadecimal number to convert specified as a string
1869
	 * @return string hexadecimal representation
1870
	 */
1871
	public function hex_to_dec($hex) {
1872
		$dec = 0;
1873
		$bitval = 1;
1874
		$len = strlen($hex);
1875
		for ($pos = ($len - 1); $pos >= 0; --$pos) {
1876
			$dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval));
1877
			$bitval = bcmul($bitval, 16);
1878
		}
1879
		return $dec;
1880
	}	
1881
	
1882
	/**
1883
	 * Intelligent Mail Barcode calculation of Frame Check Sequence
1884
	 * @param string $code_arr array of hexadecimal values (13 bytes holding 102 bits right justified).
1885
	 * @return int 11 bit Frame Check Sequence as integer (decimal base)
1886
	 * @access protected
1887
	 */
1888
	protected function imb_crc11fcs($code_arr) {
1889
		$genpoly = 0x0F35; // generator polynomial
1890
		$fcs = 0x07FF; // Frame Check Sequence
1891
		// do most significant byte skipping the 2 most significant bits
1892
		$data = hexdec($code_arr[0]) << 5;
1893 View Code Duplication
		for ($bit = 2; $bit < 8; ++$bit) {
1894
			if (($fcs ^ $data) & 0x400) {
1895
				$fcs = ($fcs << 1) ^ $genpoly;
1896
			} else {
1897
				$fcs = ($fcs << 1);
1898
			}
1899
			$fcs &= 0x7FF;
1900
			$data <<= 1;
1901
		}
1902
		// do rest of bytes
1903
		for ($byte = 1; $byte < 13; ++$byte) {
1904
			$data = hexdec($code_arr[$byte]) << 3;
1905 View Code Duplication
			for ($bit = 0; $bit < 8; ++$bit) {
1906
				if (($fcs ^ $data) & 0x400) {
1907
					$fcs = ($fcs << 1) ^ $genpoly;
1908
				} else {
1909
					$fcs = ($fcs << 1);
1910
				}
1911
				$fcs &= 0x7FF;
1912
				$data <<= 1;
1913
			}
1914
		}
1915
		return $fcs;		
1916
	}
1917
	
1918
	/**
1919
	 * Reverse unsigned short value
1920
	 * @param int $num value to reversr
1921
	 * @return int reversed value
1922
	 * @access protected
1923
	 */
1924
	protected function imb_reverse_us($num) {
1925
		$rev = 0;
1926
		for ($i = 0; $i < 16; ++$i) {
1927
			$rev <<= 1;
1928
			$rev |= ($num & 1);
1929
			$num >>= 1;
1930
		}
1931
		return $rev;
1932
	}
1933
	
1934
	/**
1935
	 * generate Nof13 tables used for Intelligent Mail Barcode
1936
	 * @param int $n is the type of table: 2 for 2of13 table, 5 for 5of13table
1937
	 * @param int $size size of table (78 for n=2 and 1287 for n=5)
1938
	 * @return array requested table
1939
	 * @access protected
1940
	 */
1941
	protected function imb_tables($n, $size) {
1942
		$table = array();
1943
		$lli = 0; // LUT lower index
1944
		$lui = $size - 1; // LUT upper index
1945
		for ($count = 0; $count < 8192; ++$count) {
1946
			$bit_count = 0;
1947
			for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
1948
				$bit_count += intval(($count & (1 << $bit_index)) != 0);
1949
			}
1950
			// if we don't have the right number of bits on, go on to the next value
1951
			if ($bit_count == $n) {
1952
				$reverse = ($this->imb_reverse_us($count) >> 3);
1953
				// if the reverse is less than count, we have already visited this pair before
1954
				if ($reverse >= $count) {
1955
					// If count is symmetric, place it at the first free slot from the end of the list.
1956
					// Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list
1957
					if ($reverse == $count) {
1958
						$table[$lui] = $count;
1959
						--$lui;
1960
					} else {
1961
						$table[$lli] = $count;
1962
						++$lli;
1963
						$table[$lli] = $reverse;
1964
						++$lli;
1965
					}
1966
				}
1967
			}
1968
		}
1969
		return $table;
1970
	}
1971
	
1972
} // end of class
1973
1974
//============================================================+
1975
// END OF FILE                                                 
1976
//============================================================+
1977
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
1978