Qrcode::raw()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 5
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class Smtp
4
 * @author Tinymeng <[email protected]>
5
 * @date: 2019/9/25 18:51
6
 */
7
namespace tinymeng\code\Gateways\qrcode;
8
use Exception;
9
use tinymeng\code\Gateways\qrcode\FrameFiller;
10
use tinymeng\code\Gateways\qrcode\QRencode;
11
use tinymeng\code\Gateways\qrcode\QRrawcode;
12
13
// Encoding modes
14
define('QR_MODE_NUL', -1);
15
define('QR_MODE_NUM', 0);
16
define('QR_MODE_AN', 1);
17
define('QR_MODE_8', 2);
18
define('QR_MODE_KANJI', 3);
19
define('QR_MODE_STRUCTURE', 4);
20
// Levels of error correction.
21
define('QR_ECLEVEL_L', 0);
22
define('QR_ECLEVEL_M', 1);
23
define('QR_ECLEVEL_Q', 2);
24
define('QR_ECLEVEL_H', 3);
25
// Supported output formats
26
define('QR_FORMAT_TEXT', 0);
27
define('QR_FORMAT_PNG',  1);
28
/**
29
 * config
30
 */
31
define('QR_CACHEABLE', true);                                                               // use cache - more disk reads but less CPU power, masks and format templates are stored there
32
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR);  // used when QR_CACHEABLE === true
33
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR);                                // default error logs dir
34
define('QR_FIND_BEST_MASK', true);                                                          // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
35
define('QR_FIND_FROM_RANDOM', false);                                                       // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
36
define('QR_DEFAULT_MASK', 2);                                                               // when QR_FIND_BEST_MASK === false
37
define('QR_PNG_MAXIMUM_SIZE',  1024);                                                       // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
38
39
define('QRSPEC_VERSION_MAX', 40);
40
define('QRSPEC_WIDTH_MAX',   177);
41
define('QRCAP_WIDTH',        0);
42
define('QRCAP_WORDS',        1);
43
define('QRCAP_REMINDER',     2);
44
define('QRCAP_EC',           3);
45
class Qrcode{
46
47
48
    public $version;
49
    public $width;
50
    public $data;
51
52
    //----------------------------------------------------------------------
53
    public function encodeMask(QRinput $input, $mask)
54
    {
55
        if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
56
            throw new Exception('wrong version');
57
        }
58
        if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
59
            throw new Exception('wrong level');
60
        }
61
62
        $raw = new QRrawcode($input);
63
64
        QRtools::markTime('after_raw');
65
66
        $version = $raw->version;
67
        $width = QRspec::getWidth($version);
68
        $frame = QRspec::newFrame($version);
69
70
        $filler = new FrameFiller($width, $frame);
71
        if(is_null($filler)) {
72
            return NULL;
73
        }
74
75
        // inteleaved data and ecc codes
76
        for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
77
            $code = $raw->getCode();
78
            $bit = 0x80;
79
            for($j=0; $j<8; $j++) {
80
                $addr = $filler->next();
81
                $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
82
                $bit = $bit >> 1;
83
            }
84
        }
85
86
        QRtools::markTime('after_filler');
87
88
        unset($raw);
89
90
        // remainder bits
91
        $j = QRspec::getRemainder($version);
92
        for($i=0; $i<$j; $i++) {
93
            $addr = $filler->next();
94
            $filler->setFrameAt($addr, 0x02);
95
        }
96
97
        $frame = $filler->frame;
98
        unset($filler);
99
100
101
        // masking
102
        $maskObj = new QRmask();
103
        if($mask < 0) {
104
105
            if (QR_FIND_BEST_MASK) {
106
                $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
107
            } else {
108
                $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
109
            }
110
        } else {
111
            $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
112
        }
113
114
        if($masked == NULL) {
115
            return NULL;
116
        }
117
118
        QRtools::markTime('after_mask');
119
120
        $this->version = $version;
121
        $this->width = $width;
122
        $this->data = $masked;
123
124
        return $this;
125
    }
126
127
    //----------------------------------------------------------------------
128
    public function encodeInput(QRinput $input)
129
    {
130
        return $this->encodeMask($input, -1);
131
    }
132
133
    //----------------------------------------------------------------------
134
    public function encodeString8bit($string, $version, $level)
135
    {
136
        if(string == NULL) {
0 ignored issues
show
Bug introduced by
The constant tinymeng\code\Gateways\qrcode\string was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
137
            throw new Exception('empty string!');
138
            return NULL;
0 ignored issues
show
Unused Code introduced by
return NULL is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
139
        }
140
141
        $input = new QRinput($version, $level);
142
        if($input == NULL) return NULL;
143
144
        $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
0 ignored issues
show
Unused Code introduced by
The call to tinymeng\code\Gateways\qrcode\QRinput::append() has too many arguments starting with str_split($string). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
        /** @scrutinizer ignore-call */ 
145
        $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
145
        if($ret < 0) {
146
            unset($input);
147
            return NULL;
148
        }
149
        return $this->encodeInput($input);
150
    }
151
152
    //----------------------------------------------------------------------
153
    public function encodeString($string, $version, $level, $hint, $casesensitive)
154
    {
155
156
        if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
157
            throw new Exception('bad hint');
158
            return NULL;
0 ignored issues
show
Unused Code introduced by
return NULL is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
159
        }
160
161
        $input = new QRinput($version, $level);
162
        if($input == NULL) return NULL;
163
164
        $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
165
        if($ret < 0) {
166
            return NULL;
167
        }
168
169
        return $this->encodeInput($input);
170
    }
171
172
    //----------------------------------------------------------------------
173
    public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
0 ignored issues
show
Unused Code introduced by
The parameter $saveandprint is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

173
    public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, /** @scrutinizer ignore-unused */ $saveandprint=false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
    {
175
        $enc = QRencode::factory($level, $size, $margin);
176
        return $enc->encodePNG($text, $outfile, $saveandprint=false);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $enc->encodePNG($text, $... $saveandprint = false) targeting tinymeng\code\Gateways\q...e\QRencode::encodePNG() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
177
    }
178
179
    //----------------------------------------------------------------------
180
    public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
181
    {
182
        $enc = QRencode::factory($level, $size, $margin);
183
        return $enc->encode($text, $outfile);
184
    }
185
186
    //----------------------------------------------------------------------
187
    public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
188
    {
189
        $enc = QRencode::factory($level, $size, $margin);
190
        return $enc->encodeRAW($text, $outfile);
191
    }
192
193
194
}