Passed
Push — master ( 596808...c6812c )
by Francimar
08:43
created

Profile   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 342
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 43
lcom 1
cbo 5
dl 0
loc 342
ccs 137
cts 137
cp 1
rs 8.96
c 0
b 0
f 0

33 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getName() 0 5 2
A getEncoding() 0 4 1
A getDefaultColumns() 0 4 1
A getColumns() 0 4 1
A setColumns() 0 14 3
A getDefaultFont() 0 4 1
A findDefaultFont() 0 16 3
A getCodePages() 0 4 1
A getDefaultCodePage() 0 4 1
A setCodePage() 0 6 1
A getFont() 0 4 1
A setFont() 0 27 5
A refresh() 0 6 1
A fontChanged() 0 3 1
A getConnection() 0 7 2
A setConnection() 0 5 1
A initialize() 0 8 2
A finalize() 0 3 1
A checkCodePage() 0 14 2
A write() 0 15 1
A writeln() 0 15 5
A getBitmapCmd() 0 4 1
A draw() 0 13 2
qrcode() 0 1 ?
A drawQrcode() 0 13 2
feed() 0 1 ?
cutter() 0 1 ?
buzzer() 0 1 ?
drawer() 0 1 ?
setAlignment() 0 1 ?
setMode() 0 1 ?
setStyle() 0 1 ?

How to fix   Complexity   

Complex Class

Complex classes like Profile 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 Profile, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Thermal\Profile;
4
5
use Thermal\Printer;
6
use Thermal\Buffer\Encoding;
7
use Thermal\Connection\Connection;
8
use Endroid\QrCode\QrCode;
9
use Thermal\Graphics\Image;
10
use Thermal\Graphics\Filter\Threshold;
11
12
abstract class Profile
13
{
14
    /**
15
     * Column count
16
     *
17
     * @var int
18
     */
19
    private $columns;
20
21
    /**
22
     * Model capabilities
23
     *
24
     * @var array
25
     */
26
    protected $capabilities;
27
28
    /**
29
     * Connection or output buffer
30
     *
31
     * @var \Thermal\Connection\Connection
32
     */
33
    private $connection;
34
35
    /**
36
     * Font name A, C or C
37
     *
38
     * @var string
39
     */
40
    private $font;
41
42
    /**
43
     * Printer default font name
44
     *
45
     * @var string
46
     */
47
    private $default_font;
48
49
    /**
50
     * Encoding
51
     *
52
     * @var \Thermal\Buffer\Encoding
53
     */
54
    private $encoding;
55
56
    /**
57
     * Profile constructor
58
     *
59
     * @param array $capabilities
60
     */
61 52
    public function __construct($capabilities)
62
    {
63 52
        $this->capabilities = $capabilities;
64 52
        $this->columns = $this->getDefaultColumns();
65 52
        $this->default_font = $this->findDefaultFont();
66 52
        $this->font = $this->getDefaultFont();
67 52
        $this->connection = null;
68 52
        $this->encoding = new Encoding($this->getDefaultCodePage());
69 52
    }
70
71 13
    public function getName()
72
    {
73 13
        $name = isset($this->capabilities['name']) ? $this->capabilities['name'] : $this->capabilities['model'];
74 13
        return $this->capabilities['brand'] . ' ' . $name;
75
    }
76
77
    /**
78
     * Printer encoding
79
     *
80
     * @return \Thermal\Buffer\Encoding
81
     */
82 19
    public function getEncoding()
83
    {
84 19
        return $this->encoding;
85
    }
86
87
    /**
88
     * Default column count
89
     *
90
     * @return int
91
     */
92 52
    public function getDefaultColumns()
93
    {
94 52
        return $this->capabilities['columns'];
95
    }
96
97
    /**
98
     * Column count for printing
99
     *
100
     * @return int
101
     */
102 4
    public function getColumns()
103
    {
104 4
        return $this->columns;
105
    }
106
107 6
    public function setColumns($columns)
108
    {
109 6
        $font = ['name' => 'Unknow'];
110
        // search for font with more columns
111
        // font list must be sorted by their number of columns
112 6
        foreach ($this->capabilities['fonts'] as $font) {
113 6
            if ($columns <= $font['columns']) {
114 6
                break;
115
            }
116
        }
117 6
        $this->setFont($font);
118 6
        $this->columns = $columns;
119 6
        return $this;
120
    }
121
122 52
    public function getDefaultFont()
123
    {
124 52
        return $this->default_font;
125
    }
126
127 52
    private function findDefaultFont()
128
    {
129 52
        foreach ($this->capabilities['fonts'] as $font) {
130 52
            if ($this->getDefaultColumns() == $font['columns']) {
131 52
                return $font;
132
            }
133
        }
134 1
        throw new \Exception(
135 1
            sprintf(
136 1
                'Default font with %d columns not found for printer "%s"',
137 1
                $this->getDefaultColumns(),
138 1
                $this->getName()
139
            ),
140 1
            404
141
        );
142
    }
143
144 3
    public function getCodePages()
145
    {
146 3
        return array_keys($this->capabilities['codepages']);
147
    }
148
149 52
    public function getDefaultCodePage()
150
    {
151 52
        return $this->capabilities['codepage'];
152
    }
153
154 14
    protected function checkCodePage($codepage)
155
    {
156 14
        if (!isset($this->capabilities['codepages'][$codepage])) {
157 1
            throw new \Exception(
158 1
                sprintf(
159 1
                    'Codepage "%s" not supported for printer "%s"',
160
                    $codepage,
161 1
                    $this->getName()
162
                ),
163 1
                401
164
            );
165
        }
166 14
        return $this;
167
    }
168
169 14
    public function setCodePage($codepage)
170
    {
171 14
        $this->getEncoding()->setCodePage($codepage);
172 14
        $this->checkCodePage($codepage);
173 14
        $this->getConnection()->write($this->capabilities['codepages'][$codepage]);
174 14
    }
175
176 6
    public function getFont()
177
    {
178 6
        return $this->font;
179
    }
180
181 8
    public function setFont($font)
182
    {
183 8
        $found = false;
184 8
        $_font = ['name' => 'Unknow'];
185 8
        foreach ($this->capabilities['fonts'] as $_font) {
186 8
            if ($_font['name'] == $font['name']) {
187 6
                $found = true;
188 6
                break;
189
            }
190
        }
191 8
        if (!$found) {
192 2
            throw new \Exception(
193 2
                sprintf(
194 2
                    'Font "%s" not found for printer "%s"',
195 2
                    $font['name'],
196 2
                    $this->getName()
197
                ),
198 2
                404
199
            );
200
        }
201 6
        if ($this->font['name'] != $_font['name']) {
202 6
            $this->fontChanged($_font, $this->font['name']);
203 6
            $this->refresh();
204
        }
205 6
        $this->font = $_font;
206 6
        return $this;
207
    }
208
209 14
    protected function refresh()
210
    {
211
        // ensure current codepage
212 14
        $this->setCodePage($this->getEncoding()->getCodePage());
213 14
        return $this;
214
    }
215
216 6
    protected function fontChanged($new_font, $old_font)
217
    {
218 6
    }
219
220
    /**
221
     * Current connection
222
     *
223
     * @return \Thermal\Connection\Connection
224
     */
225 39
    public function getConnection()
226
    {
227 39
        if ($this->connection instanceof Connection) {
228 37
            return $this->connection;
229
        }
230 2
        throw new \Exception('Connection must be set before priting', 500);
231
    }
232
233
    /**
234
     * Set current connection
235
     *
236
     * @param \Thermal\Connection\Connection $connection
237
     * @return self
238
     */
239 47
    public function setConnection($connection)
240
    {
241 47
        $this->connection = $connection;
242 47
        return $this;
243
    }
244
245 12
    public function initialize()
246
    {
247 12
        if (isset($this->capabilities['initialize'])) {
248
            // ensure defaults
249 12
            $this->getConnection()->write($this->capabilities['initialize']);
250
        }
251 12
        $this->refresh();
252 12
    }
253
254 1
    public function finalize()
255
    {
256 1
    }
257
258 7
    public function write($text, $styles)
259
    {
260 7
        $this->setMode($styles, true);
261 7
        $this->setStyle(Printer::STYLE_CONDENSED & $styles, true);
262 7
        $this->setStyle(Printer::STYLE_BOLD & $styles, true);
263 7
        $this->setStyle(Printer::STYLE_ITALIC & $styles, true);
264 7
        $this->setStyle(Printer::STYLE_UNDERLINE & $styles, true);
265 7
        $this->getConnection()->write($this->getEncoding()->encode($text, 'UTF-8'));
266 7
        $this->setStyle(Printer::STYLE_UNDERLINE & $styles, false);
267 7
        $this->setStyle(Printer::STYLE_ITALIC & $styles, false);
268 7
        $this->setStyle(Printer::STYLE_BOLD & $styles, false);
269 7
        $this->setStyle(Printer::STYLE_CONDENSED & $styles, false);
270 7
        $this->setMode($styles, false);
271 7
        return $this;
272
    }
273
274 3
    public function writeln($text, $styles, $align)
275
    {
276 3
        if ($align !== null) {
277 3
            $this->setAlignment($align);
278
        }
279 3
        if (strlen($text) > 0) {
280 3
            $this->write($text, $styles);
281
        }
282 3
        $this->feed(1);
283
        // reset align to left
284 3
        if ($align !== null && $align != Printer::ALIGN_LEFT) {
285 2
            $this->setAlignment(Printer::ALIGN_LEFT);
286
        }
287 3
        return $this;
288
    }
289
290 3
    protected function getBitmapCmd()
291
    {
292 3
        return "\e*!";
293
    }
294
295 4
    public function draw($image)
296
    {
297 4
        $width = $image->getWidth();
298 4
        $low = $width & 0xFF;
299 4
        $high = ($width >> 8) & 0xFF;
300 4
        $this->getConnection()->write("\e3\x10");
301 4
        for ($i=0; $i < $image->getLines(); $i++) {
302 4
            $data = $image->getLineData($i);
303 4
            $this->getConnection()->write($this->getBitmapCmd() . chr($low) . chr($high) . $data . "\eJ\x00");
304
        }
305 4
        $this->getConnection()->write("\e2");
306 4
        return $this;
307
    }
308
309
    /**
310
     * Draw QR Code
311
     *
312
     * @param string $data data to encode
313
     * @param int $size size of QR Code
314
     * @return void
315
     */
316
    abstract public function qrcode($data, $size);
317
318
    /**
319
     * Draw QR Code generating an image and sending to printer
320
     *
321
     * @param string $data data to encode
322
     * @param int $size size of QR Code
323
     * @return void
324
     */
325 2
    protected function drawQrcode($data, $size)
326
    {
327 2
        $qrCode = new QrCode($data);
0 ignored issues
show
Coding Style introduced by
$qrCode does not seem to conform to the naming convention (^[a-z_][a-z0-9_]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
328 2
        $qrCode->setSize(min(11, max(1, $size ?: 4)) * 50);
0 ignored issues
show
Coding Style introduced by
$qrCode does not seem to conform to the naming convention (^[a-z_][a-z0-9_]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
329 2
        $image = new Image(
330
            [
331 2
                'data' => $qrCode->writeString(),
0 ignored issues
show
Coding Style introduced by
$qrCode does not seem to conform to the naming convention (^[a-z_][a-z0-9_]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
332 2
                'name' => 'qrcode.png',
333
            ],
334 2
            new Threshold()
335
        );
336 2
        $this->draw($image);
337 2
    }
338
339
    abstract public function feed($lines);
340
    abstract public function cutter($mode);
341
    abstract public function buzzer();
342
343
    /**
344
     * @param int $number drawer id
345
     * @param int $on_time time in milliseconds that activate the drawer
346
     * @param int $off_time time in milliseconds that deactivate the drawer
347
     */
348
    abstract public function drawer($number, $on_time, $off_time);
349
350
    abstract public function setAlignment($align);
351
    abstract protected function setMode($mode, $enable);
352
    abstract protected function setStyle($style, $enable);
353
}
354