GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Test Failed
Push — master ( 15117e...3bf903 )
by Carlos
08:42
created

Pinyin::hasOption()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 * This file is part of the overtrue/pinyin.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Overtrue\Pinyin;
13
14
use InvalidArgumentException;
15
16
/*
17
 * Chinese to pinyin translator.
18
 *
19
 * @author    overtrue <[email protected]>
20
 * @copyright 2015 overtrue <[email protected]>
21
 *
22
 * @link      https://github.com/overtrue/pinyin
23 1
 * @link      http://overtrue.me
24 1
 */
25 1
26
define('PINYIN_DEFAULT', 4096);
27
define('PINYIN_TONE', 2);
28
define('PINYIN_NO_TONE', 4);
29
define('PINYIN_ASCII_TONE', 8);
30
define('PINYIN_NAME', 16);
31
define('PINYIN_KEEP_NUMBER', 32);
32
define('PINYIN_KEEP_ENGLISH', 64);
33
define('PINYIN_UMLAUT_V', 128);
34
define('PINYIN_KEEP_PUNCTUATION', 256);
35
36
/**
37
 * Class Pinyin
38
 *
39
 * @author overtrue <[email protected]>
40
 */
41
class Pinyin
42
{
43
    /**
44
     * Dict loader.
45
     *
46
     * @var \Overtrue\Pinyin\DictLoaderInterface
47
     */
48
    protected $loader;
49
50
    /**
51
     * Punctuations map.
52
     *
53
     * @var array
54
     */
55
    protected $punctuations = array(
56
        ',' => ',',
57
        '。' => '.',
58
        '!' => '!',
59
        '?' => '?',
60
        ':' => ':',
61
        '“' => '"',
62 21
        '”' => '"',
63
        '‘' => "'",
64 21
        '’' => "'",
65 21
        '_' => "_",
66
    );
67
68
    /**
69
     * Constructor.
70
     *
71
     * @param string $loaderName
72
     */
73
    public function __construct($loaderName = null)
74
    {
75 10
        $this->loader = $loaderName ?: 'Overtrue\\Pinyin\\FileDictLoader';
76
    }
77 10
78
    /**
79 10
     * Convert string to pinyin.
80
     *
81
     * @param string $string
82
     * @param int    $option
83
     *
84
     * @return array
85
     */
86
    public function convert($string, $option = PINYIN_DEFAULT)
87
    {
88
        $pinyin = $this->romanize($string, $option);
89
90 2
        return $this->splitWords($pinyin, $option);
91
    }
92 2
93
    /**
94 2
     * Convert string (person name) to pinyin.
95
     *
96
     * @param string $stringName
97
     * @param int    $option
98
     *
99
     * @return array
100
     */
101
    public function name($stringName, $option = PINYIN_NAME)
102
    {
103
        $pinyin = $this->romanize($stringName, $option);
104
105 2
        return $this->splitWords($pinyin, $option);
106
    }
107 2
108 2
    /**
109
     * Return a pinyin permalink from string.
110
     *
111 2
     * @param string $string
112
     * @param string $delimiter
113
     * @param int    $option
114
     *
115
     * @return string
116
     */
117
    public function permalink($string, $delimiter = '-', $option = PINYIN_DEFAULT)
118
    {
119
        if (\is_int($delimiter)) {
120
            list($option, $delimiter) = array($delimiter, '-');
121
        }
122 2
123
        if (!in_array($delimiter, array('_', '-', '.', ''), true)) {
124
            throw new InvalidArgumentException("Delimiter must be one of: '_', '-', '', '.'.");
125 2
        }
126 2
127
        return implode($delimiter, $this->convert($string, $option | \PINYIN_KEEP_NUMBER | \PINYIN_KEEP_ENGLISH));
128
    }
129
130
    /**
131
     * Return first letters.
132
     *
133
     * @param string $string
134
     * @param string $delimiter
135
     * @param int    $option
136
     *
137
     * @return string
138 2
     */
139
    public function abbr($string, $delimiter = '', $option = PINYIN_DEFAULT)
140 2
    {
141
        if (\is_int($delimiter)) {
142
            list($option, $delimiter) = array($delimiter, '');
143
        }
144
145
        return implode($delimiter, array_map(function ($pinyin) {
146
            return \is_numeric($pinyin) ? $pinyin : $pinyin[0];
147
        }, $this->convert($string, $option)));
148
    }
149
150
    /**
151 9
     * Chinese phrase to pinyin.
152
     *
153 9
     * @param string $string
154 9
     * @param string $delimiter
155 9
     * @param int    $option
156
     *
157 9
     * @return string
158
     */
159 9
    public function phrase($string, $delimiter = ' ', $option = PINYIN_DEFAULT)
160 9
    {
161
        if (\is_int($delimiter)) {
162 9
            list($option, $delimiter) = array($delimiter, ' ');
163
        }
164
165
        return implode($delimiter, $this->convert($string, $option));
166
    }
167
168
    /**
169
     * Chinese to pinyin sentence.
170
     *
171
     * @param string $string
172 1
     * @param string $delimiter
173
     * @param int    $option
174 1
     *
175
     * @return string
176 1
     */
177
    public function sentence($string, $delimiter = ' ', $option = \PINYIN_NO_TONE)
178
    {
179
        if (\is_int($delimiter)) {
180
            list($option, $delimiter) = array($delimiter, ' ');
181
        }
182
183
        return implode($delimiter, $this->convert($string, $option | \PINYIN_KEEP_PUNCTUATION | \PINYIN_KEEP_ENGLISH | \PINYIN_KEEP_NUMBER));;
184 21
    }
185
186 21
    /**
187 20
     * Loader setter.
188
     *
189 20
     * @param \Overtrue\Pinyin\DictLoaderInterface $loader
190 20
     *
191 20
     * @return $this
192
     */
193 21
    public function setLoader(DictLoaderInterface $loader)
194
    {
195
        $this->loader = $loader;
196
197
        return $this;
198
    }
199
200
    /**
201
     * Return dict loader,.
202
     *
203 21
     * @return \Overtrue\Pinyin\DictLoaderInterface
204
     */
205
    public function getLoader()
206 8
    {
207 21
        if (!($this->loader instanceof DictLoaderInterface)) {
208
            $dataDir = dirname(__DIR__).'/data/';
209 21
210
            $loaderName = $this->loader;
211
            $this->loader = new $loaderName($dataDir);
212
        }
213
214
        return $this->loader;
215
    }
216
217
    /**
218
     * Convert Chinese to pinyin.
219
     *
220 21
     * @param string $string
221
     * @param int    $option
222 21
     *
223
     * @return string
224 21
     */
225
    protected function romanize($string, $option = \PINYIN_DEFAULT)
226 21
    {
227 2
        $string = $this->prepare($string, $option);
228 2
229
        $dictLoader = $this->getLoader();
230
231 21
        if ($this->hasOption($option, \PINYIN_NAME)) {
232 21
            $string = $this->convertSurname($string, $dictLoader);
233
        }
234 21
235
        $dictLoader->map(function ($dictionary) use (&$string) {
236
            $string = strtr($string, $dictionary);
237
        });
238
239
        return $string;
240
    }
241
242
    /**
243
     * Convert Chinese Surname to pinyin.
244
     *
245
     * @param string                               $string
246
     * @param \Overtrue\Pinyin\DictLoaderInterface $dictLoader
247 2
     *
248 2
     * @return string
249 2
     */
250 2
    protected function convertSurname($string, $dictLoader)
251 2
    {
252
        $dictLoader->mapSurname(function ($dictionary) use (&$string) {
253 2
            foreach ($dictionary as $surname => $pinyin) {
254 2
                if (0 === strpos($string, $surname)) {
255
                    $string = $pinyin.mb_substr($string, mb_strlen($surname, 'UTF-8'), mb_strlen($string, 'UTF-8') - 1, 'UTF-8');
256 2
257
                    break;
258
                }
259
            }
260
        });
261
262
        return $string;
263
    }
264
265
    /**
266
     * Split pinyin string to words.
267 12
     *
268
     * @param string $pinyin
269 12
     * @param string $option
270
     *
271 12
     * @return array
272 10
     */
273 10
    protected function splitWords($pinyin, $option)
274 10
    {
275 10
        $split = array_filter(preg_split('/\s+/i', $pinyin));
276
277 12
        if (!$this->hasOption($option, PINYIN_TONE)) {
278
            foreach ($split as $index => $pinyin) {
279
                $split[$index] = $this->formatTone($pinyin, $option);
280
            }
281
        }
282
283
        return array_values($split);
284
    }
285
286
    /**
287
     * @param int $option
288 17
     * @param int $check
289
     *
290
     * @return bool
291 17
     */
292 17
    public function hasOption($option, $check)
293 17
    {
294 17
        return ($option & $check) === $check;
295 17
    }
296 17
297
    /**
298 17
     * Pre-process.
299 17
     *
300 16
     * @param string $string
301 16
     * @param int    $option
302 17
     *
303
     * @return string
304 17
     */
305
    protected function prepare($string, $option = \PINYIN_DEFAULT)
306
    {
307
        $string = preg_replace_callback('~[a-z0-9_-]+~i', function ($matches) {
308
            return "\t".$matches[0];
309
        }, $string);
310
311
        $regex = array('\p{Han}', '\p{Z}', '\p{M}', "\t");
312
313
        if ($this->hasOption($option, \PINYIN_KEEP_NUMBER)) {
314
            \array_push($regex, '\p{N}');
315
        }
316
317
        if ($this->hasOption($option, \PINYIN_KEEP_ENGLISH)) {
318
            \array_push($regex, 'a-zA-Z');
319
        }
320
321
        if ($this->hasOption($option, \PINYIN_KEEP_PUNCTUATION)) {
322
            $punctuations = array_merge($this->punctuations, array("\t" => ' ', '  ' => ' '));
323
            $string = trim(str_replace(array_keys($punctuations), $punctuations, $string));
324
325
            \array_push($regex, preg_quote(implode(array_merge(array_keys($this->punctuations), $this->punctuations)), '~'));
326
        }
327
328
        return preg_replace(\sprintf("~[^%s]~u", join($regex)), '', $string);
329
    }
330
331
    /**
332
     * Format.
333
     *
334
     * @param string $pinyin
335
     * @param int    $option
336
     *
337
     * @return string
338
     */
339
    protected function formatTone($pinyin, $option = \PINYIN_NO_TONE)
340
    {
341
        $replacements = array(
342
            'üē' => array('ue', 1), 'üé' => array('ue', 2), 'üě' => array('ue', 3), 'üè' => array('ue', 4),
343
            'ā' => array('a', 1), 'ē' => array('e', 1), 'ī' => array('i', 1), 'ō' => array('o', 1), 'ū' => array('u', 1), 'ǖ' => array('yu', 1),
344
            'á' => array('a', 2), 'é' => array('e', 2), 'í' => array('i', 2), 'ó' => array('o', 2), 'ú' => array('u', 2), 'ǘ' => array('yu', 2),
345
            'ǎ' => array('a', 3), 'ě' => array('e', 3), 'ǐ' => array('i', 3), 'ǒ' => array('o', 3), 'ǔ' => array('u', 3), 'ǚ' => array('yu', 3),
346
            'à' => array('a', 4), 'è' => array('e', 4), 'ì' => array('i', 4), 'ò' => array('o', 4), 'ù' => array('u', 4), 'ǜ' => array('yu', 4),
347
        );
348
349
        foreach ($replacements as $unicode => $replacement) {
350
            if (false !== strpos($pinyin, $unicode)) {
351
                $umlaut = $replacement[0];
352
353
                // https://zh.wikipedia.org/wiki/%C3%9C
354
                if ($this->hasOption($option, \PINYIN_UMLAUT_V) && $umlaut == 'yu') {
355
                    $umlaut = 'v';
356
                }
357
358
                $pinyin = str_replace($unicode, $umlaut, $pinyin).($this->hasOption($option, PINYIN_ASCII_TONE) ? $replacement[1] : '');
359
            }
360
        }
361
362
        return $pinyin;
363
    }
364
}
365