QRsplit::splitStringToQRinput()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 3
nop 4
dl 0
loc 12
rs 9.6111
c 0
b 0
f 0
1
<?php
2
namespace tinymeng\code\Gateways\qrcode;
3
4
/*
5
 * PHP QR Code encoder
6
 *
7
 * Input splitting classes
8
 *
9
 * Based on libqrencode C library distributed under LGPL 2.1
10
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
11
 *
12
 * PHP QR Code is distributed under LGPL 3
13
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
14
 *
15
 * The following data / specifications are taken from
16
 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
17
 *  or
18
 * "Automatic identification and data capture techniques -- 
19
 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
20
 *
21
 * This library is free software; you can redistribute it and/or
22
 * modify it under the terms of the GNU Lesser General Public
23
 * License as published by the Free Software Foundation; either
24
 * version 3 of the License, or any later version.
25
 *
26
 * This library is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29
 * Lesser General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU Lesser General Public
32
 * License along with this library; if not, write to the Free Software
33
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34
 */
35
class QRsplit {
36
37
    public $dataStr = '';
38
    public $input;
39
    public $modeHint;
40
41
    //----------------------------------------------------------------------
42
    public function __construct($dataStr, $input, $modeHint) 
43
    {
44
        $this->dataStr  = $dataStr;
45
        $this->input    = $input;
46
        $this->modeHint = $modeHint;
47
    }
48
    
49
    //----------------------------------------------------------------------
50
    public static function isdigitat($str, $pos)
51
    {    
52
        if ($pos >= strlen($str))
53
            return false;
54
        
55
        return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
56
    }
57
    
58
    //----------------------------------------------------------------------
59
    public static function isalnumat($str, $pos)
60
    {
61
        if ($pos >= strlen($str))
62
            return false;
63
            
64
        return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
65
    }
66
67
    //----------------------------------------------------------------------
68
    public function identifyMode($pos)
69
    {
70
        if ($pos >= strlen($this->dataStr)) 
71
            return QR_MODE_NUL;
72
            
73
        $c = $this->dataStr[$pos];
74
        
75
        if(self::isdigitat($this->dataStr, $pos)) {
76
            return QR_MODE_NUM;
77
        } else if(self::isalnumat($this->dataStr, $pos)) {
78
            return QR_MODE_AN;
79
        } else if($this->modeHint == QR_MODE_KANJI) {
80
        
81
            if ($pos+1 < strlen($this->dataStr)) 
82
            {
83
                $d = $this->dataStr[$pos+1];
84
                $word = (ord($c) << 8) | ord($d);
85
                if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
86
                    return QR_MODE_KANJI;
87
                }
88
            }
89
        }
90
91
        return QR_MODE_8;
92
    } 
93
    
94
    //----------------------------------------------------------------------
95
    public function eatNum()
96
    {
97
        $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
98
99
        $p = 0;
100
        while(self::isdigitat($this->dataStr, $p)) {
101
            $p++;
102
        }
103
        
104
        $run = $p;
105
        $mode = $this->identifyMode($p);
106
        
107
        if($mode == QR_MODE_8) {
108
            $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
109
                 + QRinput::estimateBitsMode8(1)         // + 4 + l8
110
                 - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
111
            if($dif > 0) {
112
                return $this->eat8();
113
            }
114
        }
115
        if($mode == QR_MODE_AN) {
116
            $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
117
                 + QRinput::estimateBitsModeAn(1)        // + 4 + la
118
                 - QRinput::estimateBitsModeAn($run + 1);// - 4 - la
119
            if($dif > 0) {
120
                return $this->eatAn();
121
            }
122
        }
123
        
124
        $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
125
        if($ret < 0)
126
            return -1;
127
128
        return $run;
129
    }
130
    
131
    //----------------------------------------------------------------------
132
    public function eatAn()
133
    {
134
        $la = QRspec::lengthIndicator(QR_MODE_AN,  $this->input->getVersion());
135
        $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
136
137
        $p = 0;
138
        
139
        while(self::isalnumat($this->dataStr, $p)) {
140
            if(self::isdigitat($this->dataStr, $p)) {
141
                $q = $p;
142
                while(self::isdigitat($this->dataStr, $q)) {
143
                    $q++;
144
                }
145
                
146
                $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
147
                     + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
148
                     - QRinput::estimateBitsModeAn($q); // - 4 - la
149
                     
150
                if($dif < 0) {
151
                    break;
152
                } else {
153
                    $p = $q;
154
                }
155
            } else {
156
                $p++;
157
            }
158
        }
159
160
        $run = $p;
161
162
        if(!self::isalnumat($this->dataStr, $p)) {
163
            $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
164
                 + QRinput::estimateBitsMode8(1) // + 4 + l8
165
                  - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
166
            if($dif > 0) {
167
                return $this->eat8();
168
            }
169
        }
170
171
        $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
172
        if($ret < 0)
173
            return -1;
174
175
        return $run;
176
    }
177
    
178
    //----------------------------------------------------------------------
179
    public function eatKanji()
180
    {
181
        $p = 0;
182
        
183
        while($this->identifyMode($p) == QR_MODE_KANJI) {
184
            $p += 2;
185
        }
186
        
187
        $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
188
        if($ret < 0)
189
            return -1;
190
191
        return $run;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $run seems to be never defined.
Loading history...
192
    }
193
194
    //----------------------------------------------------------------------
195
    public function eat8()
196
    {
197
        $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
198
        $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
199
200
        $p = 1;
201
        $dataStrLen = strlen($this->dataStr);
202
        
203
        while($p < $dataStrLen) {
204
            
205
            $mode = $this->identifyMode($p);
206
            if($mode == QR_MODE_KANJI) {
207
                break;
208
            }
209
            if($mode == QR_MODE_NUM) {
210
                $q = $p;
211
                while(self::isdigitat($this->dataStr, $q)) {
212
                    $q++;
213
                }
214
                $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
215
                     + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
216
                     - QRinput::estimateBitsMode8($q); // - 4 - l8
217
                if($dif < 0) {
218
                    break;
219
                } else {
220
                    $p = $q;
221
                }
222
            } else if($mode == QR_MODE_AN) {
223
                $q = $p;
224
                while(self::isalnumat($this->dataStr, $q)) {
225
                    $q++;
226
                }
227
                $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
228
                     + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
229
                     - QRinput::estimateBitsMode8($q); // - 4 - l8
230
                if($dif < 0) {
231
                    break;
232
                } else {
233
                    $p = $q;
234
                }
235
            } else {
236
                $p++;
237
            }
238
        }
239
240
        $run = $p;
241
        $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
242
        
243
        if($ret < 0)
244
            return -1;
245
246
        return $run;
247
    }
248
249
    //----------------------------------------------------------------------
250
    public function splitString()
251
    {
252
        while (strlen($this->dataStr) > 0)
253
        {
254
            if($this->dataStr == '')
255
                return 0;
256
257
            $mode = $this->identifyMode(0);
258
            
259
            switch ($mode) {
260
                case QR_MODE_NUM: $length = $this->eatNum(); break;
261
                case QR_MODE_AN:  $length = $this->eatAn(); break;
262
                case QR_MODE_KANJI:
263
                    if ($hint == QR_MODE_KANJI)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hint seems to be never defined.
Loading history...
264
                            $length = $this->eatKanji();
265
                    else    $length = $this->eat8();
266
                    break;
267
                default: $length = $this->eat8(); break;
268
            
269
            }
270
271
            if($length == 0) return 0;
272
            if($length < 0)  return -1;
273
            
274
            $this->dataStr = substr($this->dataStr, $length);
275
        }
276
    }
277
278
    //----------------------------------------------------------------------
279
    public function toUpper()
280
    {
281
        $stringLen = strlen($this->dataStr);
282
        $p = 0;
283
        
284
        while ($p<$stringLen) {
285
            $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
0 ignored issues
show
Unused Code introduced by
The call to tinymeng\code\Gateways\q...QRsplit::identifyMode() has too many arguments starting with $this->modeHint. ( Ignorable by Annotation )

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

285
            /** @scrutinizer ignore-call */ 
286
            $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);

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...
Bug Best Practice introduced by
The method tinymeng\code\Gateways\q...QRsplit::identifyMode() is not static, but was called statically. ( Ignorable by Annotation )

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

285
            /** @scrutinizer ignore-call */ 
286
            $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
Loading history...
286
            if($mode == QR_MODE_KANJI) {
287
                $p += 2;
288
            } else {
289
                if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
290
                    $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
291
                }
292
                $p++;
293
            }
294
        }
295
296
        return $this->dataStr;
297
    }
298
299
    //----------------------------------------------------------------------
300
    public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
301
    {
302
        if(is_null($string) || $string == '\0' || $string == '') {
303
            throw new Exception('empty string!!!');
0 ignored issues
show
Bug introduced by
The type tinymeng\code\Gateways\qrcode\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
304
        }
305
306
        $split = new QRsplit($string, $input, $modeHint);
307
        
308
        if(!$casesensitive)
309
            $split->toUpper();
310
            
311
        return $split->splitString();
312
    }
313
}