Completed
Push — master ( b487f1...492d4a )
by Roberto
06:15 queued 03:26
created

DefaultPrinter::setAlign()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.25

Importance

Changes 7
Bugs 0 Features 0
Metric Value
c 7
b 0
f 0
dl 0
loc 18
ccs 12
cts 16
cp 0.75
rs 9.2
cc 4
eloc 14
nc 6
nop 1
crap 4.25
1
<?php
2
3
namespace Posprint\Printers;
4
5
/*
6
 * Default class for POS thermal printers.
7
 * 
8
 * From this class all other are extended.
9
 * In the child classes should be included all the commands that are different
10
 * from those in this class, especially those specific to particular brand and 
11
 * model of printer
12
 * 
13
 * NOTE: It was built around the commands of the Epson TM-T20,
14
 * so in theory the Epson class will be almost empty just extending this class.
15
 * 
16
 * CodePage default CP437
17
 * CountyPage default LATIN
18
 * 
19
 * @category   NFePHP
20
 * @package    Posprint
21
 * @copyright  Copyright (c) 2016
22
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
23
 * @author     Roberto L. Machado <linux.rlm at gmail dot com>
24
 * @link       http://github.com/nfephp-org/posprint for the canonical source repository
25
 */
26
27
use Posprint\Printers\PrinterInterface;
28
use Posprint\Connectors\ConnectorInterface;
29
use Posprint\Connectors\Buffer;
30
use Posprint\Graphics\Graphics;
31
use Posprint\Printers\Barcodes\Barcode1DAnalysis;
32
use RuntimeException;
33
use InvalidArgumentException;
34
35
abstract class DefaultPrinter implements PrinterInterface
36
{
37
    //set standards
38
    const NUL = "\x0"; //Nulo
39
    const EOT = "\x4"; //EOT fim da transmissão
40
    const ENQ = "\x5"; //ENQ colocar na fila Pedido de status 1
41
    const HT = "\x9"; //tabulação horizontal
42
    const VT = "\xb"; //tabulação vertical
43
    const LF = "\x0a"; //Inicia a impressão e avança uma linha
44
    const FF = "\x0c"; //avança pagina
45
    const CR = "\x0d"; //retorno de carro
46
    const DLE = "\x10"; //Data Link Escape
47
    const CAN = "\x18"; //CAN Cancela linha enviada
48
    const BEL = "\x07"; //BEL sinal sonoro
49
    const ESC = "\x1b"; //escape
50
    const FS = "\x1c"; //FS
51
    const GS = "\x1d"; //GS
52
    const SO = "\x0e"; //SO Inicia modo expandido
53
    const DC1 = "\x11"; //DC1 Inicia modo enfatizado
54
    const DC2 = "\x12"; //DC2 Cancela modo condensado
55
    const DC3 = "\x13"; //DC3 Cancela modo enfatizado
56
    const DC4 = "\x14"; //DC4 Controle de dispositivo 4 Inicia modo normal
57
    const SI = "\x0f"; //Seleciona modo condensado
58
    const EM = "\x19"; //Avança 4 linhas
59
    const DEL = "\x7f"; //Cancela último caracter
60
    const NAK = "\x15"; //
61
    const SYN = "\x16"; //Sincronismo
62
    const NOTRANS = false; //not translate characters codepage
63
    const TRANS = true; //perform a character convertion to codepage
64
65
    //Cut types
66
    const CUT_FULL = 65;
67
    const CUT_PARTIAL = 66;
68
    
69
    //Image sizing options
70
    const IMG_DEFAULT = 0;
71
    const IMG_DOUBLE_WIDTH = 1;
72
    const IMG_DOUBLE_HEIGHT = 2;
73
74
    /**
75
     * List all available region pages.
76
     *
77
     * @var array
78
     */
79
    protected $aRegion = array(
80
        'USA',
81
        'FRANCE',
82
        'GERMANY',
83
        'UK',
84
        'DENMARK',
85
        'SWEDEN',
86
        'ITALY',
87
        'SPAIN',
88
        'JAPAN',
89
        'NORWAY',
90
        'DENMARK2',
91
        'SPAIN2',
92
        'LATIN',
93
        'KOREA',
94
        'SLOVENIA',
95
        'CHINA',
96
        'VIETNAM',
97
        'ARABIA'
98
    );
99
100
    /**
101
     * List all available code pages.
102
     *
103
     * @var array
104
     */
105
    protected $aCodePage = array(
106
        'CP437' => array('conv' => '437', 'table' => '0', 'desc' => 'PC437: USA, Standard Europe'),
107
        'CP850' => array('conv' => '850', 'table' => '2', 'desc' => 'PC850: Multilingual'),
108
        'CP860' => array('conv' => '860', 'table' => '3', 'desc' => 'PC860: Portuguese'),
109
        'CP863' => array('conv' => '863', 'table' => '4', 'desc' => 'PC863: Canadian-French'),
110
        'CP865' => array('conv' => '865', 'table' => '5', 'desc' => 'PC865: Nordic'),
111
        'CP851' => array('conv' => '851', 'table' => '11', 'desc' => 'PC851: Greek'),
112
        'CP853' => array('conv' => '853', 'table' => '12', 'desc' => 'PC853: Turkish'),
113
        'CP857' => array('conv' => '857', 'table' => '13', 'desc' => 'PC857: Turkish'),
114
        'CP737' => array('conv' => '737', 'table' => '14', 'desc' => 'PC737: Greek'),
115
        'ISO8859-7' => array('conv' => 'ISO8859-7', 'table' => '15', 'desc' => 'ISO8859-7: Greek'),
116
        'CP866' => array('conv' => '866', 'table' => '17', 'desc' => 'PC866: Cyrillic #2'),
117
        'CP852' => array('conv' => '852', 'table' => '18', 'desc' => 'PC852: Latin2'),
118
        'CP858' => array('conv' => '858', 'table' => '19', 'desc' => 'PC858: Euro'),
119
        'CP720' => array('conv' => '720', 'table' => '32', 'desc' => 'PC720: Arabic'),
120
        'CP855' => array('conv' => '855', 'table' => '34', 'desc' => 'PC855: Cyrillic'),
121
        'CP861' => array('conv' => '861', 'table' => '35', 'desc' => 'PC861: Icelandic'),
122
        'CP862' => array('conv' => '862', 'table' => '36', 'desc' => 'PC862: Hebrew'),
123
        'CP864' => array('conv' => '864', 'table' => '37', 'desc' => 'PC864: Arabic'),
124
        'CP869' => array('conv' => '869', 'table' => '38', 'desc' => 'PC869: Greek'),
125
        'ISO8859-2' => array('conv' => 'ISO8859-2', 'table' => '39', 'desc' => 'ISO8859-2: Latin2'),
126
        'ISO8859-15' => array('conv' => 'ISO8859-15', 'table' => '40', 'desc' => 'ISO8859-15: Latin9'),
127
        'WINDOWS-1250' => array('conv' => 'WINDOWS-1250', 'table' => '45', 'desc' => 'WPC1250: Latin2'),
128
        'WINDOWS-1251' => array('conv' => 'WINDOWS-1251', 'table' => '46', 'desc' => 'WPC1251: Cyrillic'),
129
        'WINDOWS-1252' => array('conv' => 'WINDOWS-1252', 'table' => '47', 'desc' => 'WPC1253: Greek'),
130
        'WINDOWS-1254' => array('conv' => 'WINDOWS-1254', 'table' => '48', 'desc' => 'WPC1254: Turkish'),
131
        'WINDOWS-1255' => array('conv' => 'WINDOWS-1255', 'table' => '49', 'desc' => 'WPC1255: Hebrew'),
132
        'WINDOWS-1256' => array('conv' => 'WINDOWS-1256', 'table' => '50', 'desc' => 'WPC1256: Arabic'),
133
        'WINDOWS-1257' => array('conv' => 'WINDOWS-1257', 'table' => '51', 'desc' => 'WPC1257: Baltic Rim'),
134
        'WINDOWS-1258' => array('conv' => 'WINDOWS-1258', 'table' => '52', 'desc' => 'WPC1258: Vietnamese'),
135
    );
136
    
137
    /**
138
     * Seleted code page
139
     * Defined in printer class.
140
     *
141
     * @var string
142
     */
143
    protected $codepage = 'CP437';
144
    /**
145
     * Number of codpage in printer memory.
146
     *
147
     * @var int
148
     */
149
    protected $charsetTableNum = 0;
150
    /**
151
     * Selected Region character page
152
     * Defined in printer class.
153
     *
154
     * @var string
155
     */
156
    protected $region = 'LATIN';
157
    /**
158
     * List all avaiable fonts
159
     *
160
     * @var array
161
     */
162
    protected $aFont = array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 97 => 'SA', 98 => 'SB');
163
    /**
164
     * Selected internal font.
165
     *
166
     * @var string
167
     */
168
    protected $font = 'A';
169
    /**
170
     * Resolution in dpi.
171
     *
172
     * @var int
173
     */
174
    public $dpi = 203; //dots per inch
175
    /**
176
     * Resolution in dpmm.
177
     *
178
     * @var int
179
     */
180
    public $dpmm = 8; //dots per mm
181
    /**
182
     * Maximum width paper.
183
     *
184
     * @var int
185
     */
186
    public $widthMaxmm = 80;//mm
187
    /**
188
     * Selected Width paper.
189
     *
190
     * @var int
191
     */
192
    public $widthPaper = 80;//mm
193
    /**
194
     * Maximum width for printed area.
195
     *
196
     * @var int
197
     */
198
    public $widthPrint = 72;//mm
199
    /**
200
     * Maximum width for printed area in dots.
201
     *
202
     * @var int
203
     */
204
    public $widthMaxdots = 576;//dots
205
    /**
206
     * Maximum number of characters per line.
207
     *
208
     * @var int
209
     */
210
    public $maxchars = 48;//max characters per line
211
212
    //protected property standards
213
    /**
214
     * Connector to printer.
215
     *
216
     * @var ConnectosInterface
217
     */
218
    protected $connector = null;
219
    /**
220
     * Seleted printer mode.
221
     *
222
     * @var string
223
     */
224
    protected $printerMode = 'normal';
225
    /**
226
     * Selected bold mode.
227
     *
228
     * @var bool
229
     */
230
    protected $boldMode = false;
231
    /**
232
     * Selected italic mode.
233
     *
234
     * @var bool
235
     */
236
    protected $italicMode = false;
237
    /**
238
     * Selected condenced mode.
239
     *
240
     * @var bool
241
     */
242
    protected $condensedMode = false;
243
    /**
244
     * Selected expanded mode.
245
     * @var bool
246
     */
247
    protected $expandedMode = false;
248
    /**
249
     * Seleted double higth mode.
250
     * @var bool
251
     */
252
    protected $doubleHeigth = false;
253
    /**
254
     * Selected reverse colors mode.
255
     *
256
     * @var bool
257
     */
258
    protected $reverseColors = false;
259
    /**
260
     * Selected under lined mode.
261
     *
262
     * @var bool
263
     */
264
    protected $underlineMode = false;
265
    /**
266
     * Selected rotate 90 degrees mode
267
     *
268
     * @var bool
269
     */
270
    protected $rotateMode = false;
271
    /**
272
     * Buffer class.
273
     *
274
     * @var Connectors\Buffer
275
     */
276
    protected $buffer = null;
277
    /**
278
     * Acceptable barcodes list
279
     * @var array
280
     */
281
    protected $barcode1Dlist = [
282
        'UPC_A' => 65,
283
        'UPC_E' => 66,
284
        'EAN13' => 67,
285
        'EAN8' => 68,
286
        'CODE39' => 69,
287
        'I25' => 70,
288
        'CODABAR' => 71,
289
        'CODE93' => 72,
290
        'CODE128' => 73,
291
        'GS1128' => 74,
292
        'GS1DATABAROMINI' => 75,
293
        'GS1DATABARTRUNC' => 76,
294
        'GS1DATABARLIMIT' => 77,
295
        'GS1DATABAREXPAN' => 78
296
    ];
297
    /**
298
     * List of supported models
299
     * @var array
300
     */
301
    protected $modelList = [
302
        'T20'
303
    ];
304
    /**
305
     * Selected model
306
     * @var string
307
     */
308
    protected $printerModel = 'T20';
309
310
    /**
311
     * Class constructor
312
     * Instantiates the data buffer.
313
     *
314
     * @param ConnectorInterface $conn
315
     */
316 27
    public function __construct(ConnectorInterface $conn = null)
317
    {
318 27
        if (!is_null($conn)) {
319
            $this->connector = $conn;
0 ignored issues
show
Documentation Bug introduced by
It seems like $conn of type object<Posprint\Connectors\ConnectorInterface> is incompatible with the declared type object<Posprint\Printers\ConnectosInterface> of property $connector.

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...
320
        }
321 27
        $this->buffer = new Buffer();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Posprint\Connectors\Buffer() of type object<Posprint\Connectors\Buffer> is incompatible with the declared type object<Posprint\Printers\Connectors\Buffer> of property $buffer.

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...
322 27
    }
323
    
324
    /**
325
     * Return default printer model
326
     * @param string $model
327
     * @return string|array
328
     */
329 20
    public function defaultModel($model = 'T20')
330
    {
331 20
        if (!is_null($model)) {
332 20
            $model = strtoupper(trim($model));
333 20
            if ($model == 'ALL') {
334
                return $this->modelList;
335
            }
336 20
        }
337 20
        if (array_key_exists($model, $this->modelList)) {
338
            $this->printerModel = $model;
339
        }
340 20
        return $model;
341
    }
342
    
343
    /**
344
     * Returns a default region for codepage
345
     * if param $region is null will return actual default region from class
346
     * if param $region is 'all' will return a array with all avaiable regions
347
     * if param $region is a string will set the region parameter of class and returns it.
348
     * NOTE: This command do not set the printer, only class parameters
349
     *
350
     * @param  string $region
351
     * @return string|array
352
     */
353 21
    public function defaultRegionPage($region = null)
354
    {
355 21
        if (!is_null($region)) {
356 2
            $region = strtoupper(trim($region));
357 2
            if ($region == 'ALL') {
358 1
                return $this->aRegion;
359
            }
360 2
            $reg = array_search($region, $this->aRegion, true);
361 2
            if ($reg !== false) {
362 2
                $this->region = $region;
363 2
            }
364 2
        }
365 21
        return $this->region;
366
    }
367
368
    /**
369
     * Returns a default codepage
370
     * if param $codepage is null will return actual default codepage from class
371
     * if param $codepage is 'all' will return a array with all avaiable codepages
372
     * if param $codepage is a string will set the codepage parameter of class and returns it.
373
     * NOTE: This command do not set the printer, only class parameters
374
     *
375
     * @param  string $codepage
376
     * @return string|array
377
     */
378 21
    public function defaultCodePage($codepage = null)
379
    {
380 21
        if (!is_null($codepage)) {
381 3
            $codepage = strtoupper(trim($codepage));
382 3
            if ($codepage == 'ALL') {
383 1
                return array_keys($this->aCodePage);
384
            }
385 3
            if (array_key_exists($codepage, $this->aCodePage)) {
386 3
                $this->codepage = $codepage;
387 3
                $table = $this->aCodePage[$codepage];
388 3
                $this->charsetTableNum = $table['table'];
389 3
            }
390 3
        }
391 21
        return $this->codepage;
392
    }
393
394
    /**
395
     * Returns the default printer font
396
     * A - Font A (12 x 24)
397
     * B - Font B (9 x 17)
398
     * C - Font C
399
     * D - Font D
400
     * E - Font E
401
     * Special A
402
     * Special B
403
     * Default Font A.
404
     * if param $font is null will return actual default font from class
405
     * if param $font is 'all' will return a array with all avaiable printer fonts
406
     * if param $font is a string will set the font parameter of class and returns it.
407
     * NOTE: This command do not set the printer, only class parameters
408
     *
409
     * @param  string $font
410
     * @return array|string
411
     */
412 22
    public function defaultFont($font = null)
413
    {
414 22
        if (!is_null($font)) {
415 3
            $font = strtoupper(trim($font));
416 3
            if ($font == 'ALL') {
417
                //return array
418 1
                return $this->aFont;
419
            }
420
            //set $this->font
421 2
            $fonts = array_flip($this->aFont);
422 2
            $keys = array_keys($fonts);
423 2
            $reg = array_search($font, $keys, true);
424 2
            if ($reg !== false) {
425 2
                $this->font = $font;
426 2
            }
427 2
        }
428 21
        return $this->font;
429
    }
430
431
    /**
432
     * initialize printer
433
     * Clears the data in the print buffer and resets the printer modes to
434
     * the modes that were in effect when the power was turned on.
435
     */
436 21
    public function initialize()
437
    {
438 21
        $this->rotateMode = false;
439 21
        $this->boldMode = false;
440 21
        $this->italicMode = false;
441 21
        $this->underlineMode = false;
442 21
        $this->printerMode = 'normal';
443 21
        $this->defaultModel();
444 21
        $this->defaultCodePage();
445 21
        $this->defaultRegionPage();
446 21
        $this->defaultFont();
447 21
        $this->buffer->write(self::ESC.'@');
448 21
        $this->setPrintMode();
449 21
        $this->setFont();
450 21
        $this->setCodePage();
451 21
        $this->setRegionPage();
452 21
    }
453
454
    /**
455
     * Set the printer mode.
456
     */
457
    abstract public function setPrintMode($mode = null);
458
    
459
    /**
460
     * Set a codepage table in printer.
461
     *
462
     * @param string $codepage
463
     */
464 20
    public function setCodePage($codepage = null)
465
    {
466 20
        $codepage = $this->defaultCodePage($codepage);
0 ignored issues
show
Unused Code introduced by
$codepage is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
467 20
        $this->buffer->write(self::ESC.'t'.chr($this->charsetTableNum));
468 20
    }
469
470
    /**
471
     * Set a region page.
472
     * The numeric key of array $this->aRegion is the command parameter.
473
     *
474
     * @param string $region
475
     */
476 20
    public function setRegionPage($region = null)
477
    {
478 20
        $region = $this->defaultRegionPage($region);
479 20
        $mode = array_keys($this->aRegion, $region, true);
480 20
        $this->buffer->write(self::ESC.'R'.chr($mode[0]));
481 20
    }
482
    
483
    /**
484
     * Set a printer font
485
     * If send a valid font name will set the printer otherelse a default font is selected
486
     *
487
     * @param string $font
488
     */
489 20
    public function setFont($font = null)
490
    {
491 20
        $font = $this->defaultFont($font);
492 20
        $mode = array_keys($this->aFont, $font, true);
493 20
        $this->buffer->write(self::ESC.'M'.chr($mode[0]));
494 20
    }
495
496
    /**
497
     * Set emphasys mode on or off.
498
     */
499 1
    public function setBold()
500
    {
501 1
        $mode = 1;
502 1
        if ($this->boldMode) {
503 1
            $mode = 0;
504 1
        }
505 1
        $this->boldMode = ! $this->boldMode;
506 1
        $this->buffer->write(self::ESC . 'E' . chr($mode));
507 1
    }
508
509
    /**
510
     * Set underline mode on or off.
511
     */
512 1
    public function setUnderlined()
513
    {
514 1
        $mode = 1;
515 1
        if ($this->underlineMode) {
516 1
            $mode = 0;
517 1
        }
518 1
        $this->underlineMode = ! $this->underlineMode;
519 1
        $this->buffer->write(self::ESC . '-' . chr($mode));
520 1
    }
521
    
522
    /**
523
     * Set italic mode on or off
524
     *
525
     * @return bool
526
     */
527
    public function setItalic()
528
    {
529
        //dont exists in this printer
530
    }
531
    
532
    /**
533
     * Aligns all data in one line to the selected layout in standard mode.
534
     * L - left  C - center  R - rigth
535
     *
536
     * @param string $align
537
     */
538 1
    public function setAlign($align = null)
539
    {
540 1
        if (is_null($align)) {
541
            $align = 'L';
542
        }
543 1
        $value = strtoupper($align);
544
        switch ($value) {
545 1
            case 'C':
546 1
                $mode = 1;
547 1
                break;
548 1
            case 'R':
549
                $mode = 2;
550
                break;
551 1
            default:
552 1
                $mode = 0;
553 1
        }
554 1
        $this->buffer->write(self::ESC . 'a' . chr($mode));
555 1
    }
556
    
557
    /**
558
     * Turns white/black reverse print On or Off for characters.
559
     * n = odd: On, n = even: Off.
560
     */
561 1
    public function setReverseColors()
562
    {
563 1
        $mode = 0;
564 1
        $this->reverseColors = ! $this->reverseColors;
565 1
        if ($this->reverseColors) {
566 1
            $mode = 1;
567 1
        }
568 1
        $this->buffer->write(self::GS.'B'.chr($mode));
569 1
    }
570
    
571
    /**
572
     * Set expanded mode.
573
     *
574
     * @param int $size multiplies normal size 1 - 8
575
     */
576 1
    public function setExpanded($size = null)
577
    {
578 1
        $size = self::validateInteger($size, 1, 8, 1);
579
        $aSize = [
580 1
            [0, 0],
581 1
            [16, 1],
582 1
            [32, 2],
583 1
            [48, 3],
584 1
            [64, 4],
585 1
            [80, 5],
586 1
            [96, 6],
587 1
            [112, 7]
588 1
        ];
589 1
        $mode = $aSize[$size-1][0] + $aSize[$size-1][1];
590 1
        $this->buffer->write(self::ESC.'!'.chr($mode));
591 1
    }
592
593
    /**
594
     * Set condensed mode.
595
     */
596
    public function setCondensed()
597
    {
598
        $this->setExpanded(1);
599
        $this->setFont('B');
600
    }
601
    
602
    /**
603
     * Set rotate 90 degrees.
604
     */
605 1
    public function setRotate90()
606
    {
607 1
        $this->rotateMode = !$this->rotateMode;
608 1
        $mode = 0;
609 1
        if ($this->rotateMode) {
610 1
            $mode = 1;
611 1
        }
612 1
        $this->buffer->write(self::ESC.'V'.chr($mode));
613 1
    }
614
    
615
    /**
616
     * Send message or command to buffer
617
     * when sending commands is not required to convert characters,
618
     * so the variable may translate by false.
619
     *
620
     * @param string $text
621
     */
622 1
    public function text($text = '')
623
    {
624 1
        $text = $this->translate($text);
625 1
        $this->buffer->write($text);
626 1
    }
627
628
    /**
629
     * Set horizontal and vertical motion units
630
     * $horizontal => character spacing 1/x"
631
     * $vertical => line spacing 1/y".
632
     *
633
     * @param int $horizontal
634
     * @param int $vertical
635
     */
636 1
    public function setSpacing($horizontal = 30, $vertical = 30)
637
    {
638 1
        $horizontal = self::validateInteger($horizontal, 0, 255, 30);
639 1
        $vertical = self::validateInteger($vertical, 0, 255, 30);
640 1
        $this->buffer->write(self::GS.'P'.chr($horizontal).chr($vertical));
641 1
    }
642
643
    /**
644
     * Set right-side character spacing
645
     * 0 ≤ n ≤ 255 => 1/x".
646
     *
647
     * @param int $value
648
     */
649 1
    public function setCharSpacing($value = 3)
650
    {
651 1
        $value = self::validateInteger($value, 0, 255, 0);
652 1
        $this->buffer->write(self::ESC.' '.chr($value));
653 1
    }
654
655
    /**
656
     * Line spacing
657
     * The default is set to zero and 30/180 "
658
     * any different number of zero will generate multiples of.
659
     * n  1/180-inch vertical motion
660
     * normal paragraph 30/180" => 4.23 mm
661
     *
662
     * @param int $paragraph
0 ignored issues
show
Bug introduced by
There is no parameter named $paragraph. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
663
     */
664 1
    public function setParagraph($value = 0)
665
    {
666 1
        $value = self::validateInteger($value, 0, 255, 0);
667 1
        $paragraph = ceil($value);
668 1
        if ($paragraph == 0) {
669 1
            $this->buffer->write(self::ESC.'2');
670 1
            return;
671
        }
672 1
        if ($paragraph < 25) {
673
            $paragraph = 25;
674 1
        } elseif ($paragraph > 255) {
675
            $paragraph = 255;
676
        }
677 1
        $this->buffer->write(self::ESC.'3'.chr($paragraph));
678 1
    }
679
680
    /**
681
     * Prints data and feeds paper n lines
682
     * ESC d n Prints data and feeds paper n lines.
683
     *
684
     * @param integer $lines
685
     */
686 1
    public function lineFeed($lines = 1)
687
    {
688 1
        $lines = self::validateInteger($lines, 0, 255, 1);
689 1
        if ($lines == 1) {
690 1
            $this->buffer->write(self::LF);
691 1
            return;
692
        }
693 1
        $this->buffer->write(self::ESC.'d'.chr($lines));
694 1
    }
695
696
    /**
697
     * Prints data and feeds paper n dots
698
     * ESC J n Prints data and feeds paper n dots.
699
     *
700
     * @param int $dots
701
     */
702 1
    public function dotFeed($dots = 1)
703
    {
704 1
        $dots = self::validateInteger($dots, 0, 80, 0);
705 1
        $this->buffer->write(self::ESC.'J'.chr($dots));
706 1
    }
707
708
    /**
709
     * Generate a pulse, for opening a cash drawer if one is connected.
710
     * The default settings should open an Epson drawer.
711
     *
712
     * @param int $pin    0 or 1, for pin 2 or pin 5 kick-out connector respectively.
713
     * @param int $on_ms  pulse ON time, in milliseconds.
714
     * @param int $off_ms pulse OFF time, in milliseconds.
715
     */
716 1
    public function pulse($pin = 0, $on_ms = 120, $off_ms = 240)
717
    {
718 1
        $pin = self::validateInteger($pin, 0, 1, 0);
719 1
        $on_ms = self::validateInteger($on_ms, 1, 511, 120);
720 1
        $off_ms = self::validateInteger($off_ms, 1, 511, 240);
721 1
        $this->buffer->write(self::ESC.'p'.chr($pin + 48).chr($on_ms / 2).chr($off_ms / 2));
722 1
    }
723
724
    /**
725
     * Cut the paper.
726
     *
727
     * @param int $mode  FULL or PARTIAL. If not specified, FULL will be used.
728
     * @param int $lines Number of lines to feed after cut
729
     */
730 1
    public function cut($mode = 'PARTIAL', $lines = 3)
731
    {
732 1
        $lines = self::validateInteger($lines, 1, 10, 3);
733 1
        if ($mode == 'FULL') {
734 1
            $mode = self::CUT_FULL;
735 1
        } else {
736 1
            $mode = self::CUT_PARTIAL;
737
        }
738 1
        $this->buffer->write(self::GS.'V'.chr($mode).chr($lines));
739 1
    }
740
741
    /**
742
     * Implements barcodes 1D
743
     * GS k m n d1...dn
744
     * Prints bar code. n specifies the data length.
745
     *   m    bar code system             number of d (=k)
746
     *  "A"     UPC-A                       11 or 12
747
     *  "B"     UPC-E                       6, 7, 8, 11 or 12
748
     *  "C"     JAN13 / EAN13               12 or 13
749
     *  "D"     JAN8 / EAN8                 7 or 8
750
     *  "E"     CODE39                      1 or more
751
     *  "F"     ITF                         even
752
     *  "G"     CODABAR (NW-7)              2 or more
753
     *  "H"     CODE93                      1–255
754
     *  "I"     CODE128                     2–255
755
     *  "J"     GS1-128                     2–255
756
     *  "K"     GS1 DataBar Omnidirectional 13
757
     *  "L"     GS1 DataBar Truncated       13
758
     *  "M"     GS1 DataBar Limited         13
759
     *  "N"     GS1 DataBar Expanded        2–255.
760
     *
761
     *  GS h n Sets bar code height to n dots.
762
     *  GS w n Sets bar width of bar code. n = 2–6 (thin–thick)
763
     *  GS H n Selects print position of HRI characters.
764
     *           n = 0, "0": Not printed
765
     *           n = 1, "1": Above the bar code
766
     *           n = 2, "2": Below the bar code
767
     *           n = 3, "3": Both above and below the bar code
768
     *  GS f n Selects font for the HRI characters.
769
     *           n = 0, "0": Font A,
770
     *           n = 1, "1": Font B
771
     *
772
     * @param string $data
773
     * @param int    $type        Default CODE128
774
     * @param int    $height
775
     * @param int    $lineWidth
776
     * @param string $txtPosition
777
     * @param string $txtFont
778
     */
779 1
    public function barcode(
780
        $data = '123456',
781
        $type = 'CODE128',
782
        $height = 162,
783
        $lineWidth = 2,
784
        $txtPosition = 'none',
785
        $txtFont = ''
786
    ) {
787
        switch ($txtPosition) {
788 1
            case 'Above':
789
                $tPos = 1;
790
                break;
791 1
            case 'Below':
792
                $tPos = 2;
793
                break;
794 1
            case 'Both':
795
                $tPos = 3;
796
                break;
797 1
            default:
798
                //none
799 1
                $tPos = 0;
800 1
        }
801 1
        $font = 0;
802 1
        if ($txtFont === 'B') {
803
            $font = 1;
804
        }
805 1
        if (! $data = Barcodes\Barcode1DAnalysis::validate($data, $type)) {
806
            throw new \InvalidArgumentException('Data or barcode type is incorrect.');
807
        }
808 1
        if (! array_key_exists($type, $this->barcode1Dlist)) {
809
            throw new \InvalidArgumentException('This barcode type is not listed.');
810
        }
811 1
        $id = $this->barcode1Dlist[$type];
812 1
        if (is_null($id)) {
813
            return;
814
        }
815 1
        $height = self::validateInteger($height, 1, 255, 4);
816 1
        $lineWidth = self::validateInteger($lineWidth, 1, 6, 2);
817 1
        $nlen = strlen($data);
818
        //set barcode height
819 1
        $this->buffer->write(self::GS.'h'.chr($height));
820
        //set barcode bar width
821 1
        $this->buffer->write(self::GS.'w'.chr($lineWidth));
822
        //Selects print position of HRI characters.
823 1
        $this->buffer->write(self::GS.'H'.chr($tPos));
824
        //Selects font for the HRI characters.
825 1
        $this->buffer->write(self::GS.'f'.chr($font));
826
        //Print barcode
827 1
        $this->buffer->write(self::GS.'k'.chr($id).chr($nlen).$data);
828 1
    }
829
    
830
    /**
831
     * Print PDF 417 2D barcode
832
     * @param string $data
833
     * @param integer $ecc
834
     * @param integer $pheight
835
     * @param integer $pwidth
836
     * @param integer $colunms
837
     * @return boolean
838
     */
839
    public function barcodePDF417($data = '', $ecc = 5, $pheight = 2, $pwidth = 2, $colunms = 3)
840
    {
841
        if (empty($data)) {
842
            return false;
843
        }
844
        $ecc = self::validateInteger($ecc, 0, 8, 5);
845
        $pheight = self::validateInteger($pheight, 1, 8, 2);
846
        $n = $ecc + 48;
847
        $length = strlen($data);
848
        $pH = intval($length / 256);
849
        $pL = ($length % 256);
850
        //Set the number of columns in the data region
851
        //GS (   k  pL pH cn fn n
852
        //29 40 107 3   0 48 65 n
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
853
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(65).chr(0));
854
        //Set the number of rows
855
        //GS  (      k   pL  pH  cn fn n
856
        //29  40    107  3    0  48 66 n
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
857
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(66).chr(0));
858
        //Set the width of the module
859
        //GS  (   k   pL   pH  cn  fn n
860
        //29  40 107  3    0   48  67 n
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
861
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(67).chr(0));
862
        //Set the row height
863
        //GS  (    k   pL  pH  cn  fn n
864
        //29  40  107  3   0   48  68 n
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
865
        //pheight 3 or 5 time pwidth
866
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(68).chr($pheight));
867
        //Set the error correction level
868
        //GS  (    k    pL  pH     cn fn m n
869
        //29  40  107    4   0     48 69 m n n = 48 - 56
870
        $this->buffer->write(self::GS."(k".chr(4).chr(0).chr(48).chr(69).chr(58).chr($n));
871
        //Select the options
872
        //GS  (    k    pL   pH   cn   fn   n
873
        //29  40  107   3     0   48   70   n
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
874
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(70).chr(0));
875
        //Store the data in the symbol storage area
876
        //GS  (   k   pL  pH   cn  fn  m   d1...dk
877
        //29  40 107  pL  pH   48  80  48  d1...dk
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
878
        $this->buffer->write(self::GS."(k".chr($pL).chr($pH).chr(48).chr(80).chr(48).$data);
879
        //Print the symbol data in the symbol storage area
880
        //GS  (   k   pL  pH  cn  fn m
881
        //29  40 107  3    0   48  81 m
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
882
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(48).chr(81).chr(0));
883
    }
884
  
885
    /**
886
     * Prints QRCode
887
     *
888
     * @param string $data   barcode data
889
     * @param string $level  correction level L,M,Q ou H
890
     * @param int    $modelo QRCode model 1, 2 ou 0 Micro
891
     * @param int    $wmod   width bar 3 ~ 16
892
     */
893 1
    public function barcodeQRCode($data = '', $level = 'L', $modelo = 2, $wmod = 4)
894
    {
895
        //set model of QRCode
896 1
        $n1 = 50;
897 1
        if ($modelo == 1) {
898
            $n1 = 49;
899
        }
900
        //select QR model
901 1
        $this->buffer->write(self::GS."(k".chr(4).chr(0).chr(49).chr(65).chr($n1).chr(0));
902
        //set module bar width
903 1
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(49).chr(67).chr($wmod));
904
        //set error correction level
905 1
        $level = strtoupper($level);
906
        switch ($level) {
907 1
            case 'L':
908
                $n = 48;
909
                break;
910 1
            case 'M':
911 1
                $n = 49;
912 1
                break;
913
            case 'Q':
914
                $n = 50;
915
                break;
916
            case 'H':
917
                $n = 51;
918
                break;
919
            default:
920
                $n = 49;
921
        }
922 1
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(49).chr(69).chr($n));
923
        //set data for QR Code assuming print only alphanumeric data
924 1
        $len = strlen($data) + 3;
925 1
        $pH = ($len / 256);
926 1
        $pL = $len % 256;
927 1
        $this->buffer->write(self::GS."(k".chr($pL).chr($pH).chr(49).chr(80).chr(48).$data);
928
        //Print QR Code
929 1
        $this->buffer->write(self::GS."(k".chr(3).chr(0).chr(49).chr(81).chr(48));
930 1
    }
931
932
    /**
933
     * Return all data buffer.
934
     *
935
     * @param string $type specifies the return format
936
     */
937 20
    public function getBuffer($type = '')
938
    {
939
        switch ($type) {
940 20
            case 'binA':
941
                //returns a binary array of buffer
942
                $resp = $this->buffer->getDataBinary(true);
943
                break;
944 20
            case 'binS':
945
                //returns a binary string of buffer
946 20
                $resp = $this->buffer->getDataBinary(false);
947 20
                break;
948
            case 'b64A':
949
                //returns a base64 encoded array of buffer
950
                $resp = $this->buffer->getDataBase64(true);
951
                break;
952
            case 'b64S':
953
                //returns a base64 encoded string of buffer
954
                $resp = $this->buffer->getDataBase64(false);
955
                break;
956
            case 'json':
957
                //returns a json encoded of array buffer
958
                $resp = $this->buffer->getDataJson();
959
                break;
960
            case 'readA':
961
                //returns a human readable format of array buffer
962
                //only for debug reasons
963
                $resp = $this->buffer->getDataReadable(true);
964
                break;
965
            default:
966
                //returns a human readable format of string buffer
967
                //only for debug reasons
968
                $resp = $this->buffer->getDataReadable(false);
969
        }
970 20
        return $resp;
971
    }
972
973
    /**
974
     * Send commands from buffer to connector printer.
975
     */
976
    public function send(ConnectorInterface $conn = null)
977
    {
978
        if (!is_null($conn)) {
979
            $this->connector = $conn;
0 ignored issues
show
Documentation Bug introduced by
It seems like $conn of type object<Posprint\Connectors\ConnectorInterface> is incompatible with the declared type object<Posprint\Printers\ConnectosInterface> of property $connector.

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...
980
        }
981
        if (is_null($this->connector)) {
982
            return $this->getBuffer();
983
        }
984
        $aCmds = $this->getBuffer('binA');
985
        foreach ($aCmds as $cmd) {
986
            $this->connector->write($cmd);
987
        }
988
    }
989
990
    /**
991
     * Insert a image.
992
     *
993
     * @param  string $filename Path to image file
994
     * @param  float  $width
995
     * @param  float  $height
996
     * @param  int    $size     0-normal 1-Double Width 2-Double Heigth
997
     * @throws RuntimeException
998
     */
999 1
    public function putImage($filename = '', $width = null, $height = null, $size = 0)
1000
    {
1001
        try {
1002 1
            $img = new Graphics($filename, $width, $height);
1003 1
        } catch (RuntimeException $e) {
1004
            throw new RuntimeException($e->getMessage());
1005
        } catch (InvalidArgumentException $e) {
1006
            throw new RuntimeException($e->getMessage());
1007
        }
1008 1
        $size = self::validateInteger($size, 0, 3, 0);
1009 1
        $imgHeader = self::dataHeader(array($img->getWidth(), $img->getHeight()), true);
1010 1
        $tone = '0';
1011 1
        $colors = '1';
1012 1
        $xm = (($size & self::IMG_DOUBLE_WIDTH) == self::IMG_DOUBLE_WIDTH) ? chr(2) : chr(1);
1013 1
        $ym = (($size & self::IMG_DOUBLE_HEIGHT) == self::IMG_DOUBLE_HEIGHT) ? chr(2) : chr(1);
1014 1
        $header = $tone.$xm.$ym.$colors.$imgHeader;
1015 1
        $this->sendGraphicsData('0', 'p', $header.$img->getRasterImage());
1016 1
        $this->sendGraphicsData('0', '2');
1017 1
    }
1018
1019
    /**
1020
     * Close and clean buffer
1021
     * All data will be lost.
1022
     */
1023
    public function close()
1024
    {
1025
        $this->buffer->close();
1026
    }
1027
    
1028
    /**
1029
     * Wrapper for GS ( L, to calculate and send correct data length.
1030
     *
1031
     * @param string $m    Modifier/variant for function. Usually '0'.
1032
     * @param string $fn   Function number to use, as character.
1033
     * @param string $data Data to send.
1034
     */
1035 1
    protected function sendGraphicsData($m, $fn, $data = '')
1036
    {
1037 1
        $header = $this->intLowHigh(strlen($data) + 2, 2);
1038 1
        $this->buffer->write(self::GS.'(L'.$header.$m.$fn.$data);
1039 1
    }
1040
1041
    /**
1042
     * Generate two characters for a number:
1043
     * In lower and higher parts, or more parts as needed.
1044
     *
1045
     * @param int $int    Input number
0 ignored issues
show
Bug introduced by
There is no parameter named $int. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1046
     * @param int $length The number of bytes to output (1 - 4).
1047
     */
1048 1
    protected static function intLowHigh($input, $length)
1049
    {
1050 1
        $maxInput = (256 << ($length * 8) - 1);
0 ignored issues
show
Unused Code introduced by
$maxInput is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1051 1
        $outp = '';
1052 1
        for ($i = 0; $i < $length; ++$i) {
1053 1
            $outp .= chr($input % 256);
1054 1
            $input = (int) ($input / 256);
1055 1
        }
1056 1
        return $outp;
1057
    }
1058
1059
    /**
1060
     * Convert widths and heights to characters.
1061
     * Used before sending graphics to set the size.
1062
     *
1063
     * @param  array $inputs
1064
     * @param  bool  $long   True to use 4 bytes, false to use 2
1065
     * @return string
1066
     */
1067 1
    protected static function dataHeader(array $inputs, $long = true)
1068
    {
1069 1
        $outp = array();
1070 1
        foreach ($inputs as $input) {
1071 1
            if ($long) {
1072 1
                $outp[] = self::intLowHigh($input, 2);
1073 1
            } else {
1074
                $input = self::validateInteger($input, 0, 255, 0);
1075
                $outp[] = chr($input);
1076
            }
1077 1
        }
1078 1
        return implode('', $outp);
1079
    }
1080
1081
    /**
1082
     * Verify if the argument given is not a boolean.
1083
     *
1084
     * @param  bool $test    the input to test
1085
     * @param  bool $default the default value
1086
     * @return bool
1087
     */
1088
    protected static function validateBoolean($test, $default)
1089
    {
1090
        if (!($test === true || $test === false)) {
1091
            return $default;
1092
        }
1093
        return $test;
1094
    }
1095
1096
    /**
1097
     * Verify if the argument given is not an integer within the specified range.
1098
     * will return default instead
1099
     *
1100
     * @param  int $test    the input to test
1101
     * @param  int $min     the minimum allowable value (inclusive)
1102
     * @param  int $max     the maximum allowable value (inclusive)
1103
     * @param  int $default the default value
1104
     * @return int
1105
     */
1106 10
    protected static function validateInteger($test, $min, $max, $default)
1107
    {
1108 10
        if (!is_integer($test) || $test < $min || $test > $max) {
1109 1
            return $default;
1110
        }
1111 10
        return $test;
1112
    }
1113
1114
    /**
1115
     * Verify if the argument given can't be cast to a string.
1116
     *
1117
     * @param  string $test    the input to test
1118
     * @param  string $default the default value
1119
     * @return string
1120
     */
1121
    protected static function validateString($test, $default)
1122
    {
1123
        if (is_object($test) && !method_exists($test, '__toString')) {
1124
            return $default;
1125
        }
1126
        return $test;
1127
    }
1128
    
1129
    /**
1130
     * Translate the text from UTF-8 for the specified codepage
1131
     * this translation uses "iconv" and admits texts ONLY in UTF-8.
1132
     *
1133
     * @param  string $text
1134
     * @return string
1135
     */
1136 1
    protected function translate($text = '')
1137
    {
1138 1
        $indCode = $this->defaultCodePage();
1139 1
        if (!empty($indCode)) {
1140 1
            $codep = $this->aCodePage[$indCode];
1141 1
            if (!empty($codep)) {
1142 1
                $text = iconv('UTF-8', $codep['conv'], $text);
1143 1
            }
1144 1
        }
1145 1
        return $text;
1146
    }
1147
}
1148