mirror of
https://github.com/jkjoy/Typecho-Theme-Puock.git
synced 2026-06-09 20:54:13 +00:00
1.1.1
Implemented a function to handle and validate user input in the main application module. This improves input reliability and prepares the codebase for future enhancements.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"overtrue/pinyin": "^4.1"
|
||||
}
|
||||
}
|
||||
Generated
+92
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1d353c32c45b49f759b47ca83156c5c1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "overtrue/pinyin",
|
||||
"version": "4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/overtrue/pinyin.git",
|
||||
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/overtrue/pinyin/zipball/4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
|
||||
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"phpunit/phpunit": "~8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-push": [
|
||||
"composer test",
|
||||
"composer check-style"
|
||||
],
|
||||
"pre-commit": [
|
||||
"composer test",
|
||||
"composer fix-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/const.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Overtrue\\Pinyin\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com",
|
||||
"homepage": "http://github.com/overtrue"
|
||||
}
|
||||
],
|
||||
"description": "Chinese to pinyin translator.",
|
||||
"homepage": "https://github.com/overtrue/pinyin",
|
||||
"keywords": [
|
||||
"Chinese",
|
||||
"Pinyin",
|
||||
"cn2pinyin"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/overtrue/pinyin/issues",
|
||||
"source": "https://github.com/overtrue/pinyin/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-04-27T10:17:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
+22
-39
@@ -161,6 +161,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['likeup']) && isset($_
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机封面
|
||||
*/
|
||||
@@ -304,6 +305,7 @@ function get_permalink($cid) {
|
||||
return $options->siteUrl . '?cid=' . $cid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有评论者信息的函数
|
||||
*/
|
||||
@@ -315,6 +317,7 @@ function getAllCommenters() {
|
||||
$query = $db->select('author, mail, COUNT(*) as comment_count, url')
|
||||
->from('table.comments')
|
||||
->where('status = ?', 'approved') // 只统计已通过审核的评论
|
||||
->where('authorId != ?', 1) // 排除ID为1的管理员
|
||||
->group('mail')
|
||||
->order('comment_count', Typecho_Db::SORT_DESC);
|
||||
|
||||
@@ -846,53 +849,33 @@ function getPermalinkFromCoid($coid) {
|
||||
if (empty($row)) return '';
|
||||
return '<a href="#comment-'.$coid.'" class="c-sub">@'.$row['author'].'</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 全部标签按字母书序排列
|
||||
*/
|
||||
// 获取中文字符首字母的函数
|
||||
// 引入 Composer 自动加载
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
use Overtrue\Pinyin\Pinyin;
|
||||
|
||||
function getFirstChar($str) {
|
||||
if (empty($str)) return '#';
|
||||
|
||||
// 如果是数字
|
||||
if (is_numeric($str[0])) {
|
||||
|
||||
$pinyin = new Pinyin();
|
||||
$firstChar = mb_substr($str, 0, 1, 'UTF-8');
|
||||
|
||||
// 数字
|
||||
if (is_numeric($firstChar)) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// 如果是英文字母
|
||||
$firstChar = ord($str[0]);
|
||||
if ($firstChar >= ord('A') && $firstChar <= ord('z')) {
|
||||
return strtoupper($str[0]);
|
||||
|
||||
// 英文字母
|
||||
if (preg_match('/^[a-zA-Z]$/', $firstChar)) {
|
||||
return strtoupper($firstChar);
|
||||
}
|
||||
|
||||
// 如果是中文
|
||||
$s = iconv('UTF-8', 'gb2312', $str);
|
||||
if (strlen($s) < 2) return '#';
|
||||
|
||||
$asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
|
||||
if ($asc >= -20319 && $asc <= -20284) return 'A';
|
||||
if ($asc >= -20283 && $asc <= -19776) return 'B';
|
||||
if ($asc >= -19775 && $asc <= -19219) return 'C';
|
||||
if ($asc >= -19218 && $asc <= -18711) return 'D';
|
||||
if ($asc >= -18710 && $asc <= -18527) return 'E';
|
||||
if ($asc >= -18526 && $asc <= -18240) return 'F';
|
||||
if ($asc >= -18239 && $asc <= -17923) return 'G';
|
||||
if ($asc >= -17922 && $asc <= -17418) return 'H';
|
||||
if ($asc >= -17417 && $asc <= -16475) return 'J';
|
||||
if ($asc >= -16474 && $asc <= -16213) return 'K';
|
||||
if ($asc >= -16212 && $asc <= -15641) return 'L';
|
||||
if ($asc >= -15640 && $asc <= -15166) return 'M';
|
||||
if ($asc >= -15165 && $asc <= -14923) return 'N';
|
||||
if ($asc >= -14922 && $asc <= -14915) return 'O';
|
||||
if ($asc >= -14914 && $asc <= -14631) return 'P';
|
||||
if ($asc >= -14630 && $asc <= -14150) return 'Q';
|
||||
if ($asc >= -14149 && $asc <= -14091) return 'R';
|
||||
if ($asc >= -14090 && $asc <= -13319) return 'S';
|
||||
if ($asc >= -13318 && $asc <= -12839) return 'T';
|
||||
if ($asc >= -12838 && $asc <= -12557) return 'W';
|
||||
if ($asc >= -12556 && $asc <= -11848) return 'X';
|
||||
if ($asc >= -11847 && $asc <= -11056) return 'Y';
|
||||
if ($asc >= -11055 && $asc <= -10247) return 'Z';
|
||||
return '#';
|
||||
|
||||
// 中文转拼音首字母
|
||||
$abbr = $pinyin->abbr($firstChar, '');
|
||||
return strtoupper($abbr[0] ?? '#');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit7f036e4555c1f5c49b96f869c5b4f1bf::getLoader();
|
||||
Vendored
+579
@@ -0,0 +1,579 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see https://www.php-fig.org/psr/psr-0/
|
||||
* @see https://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var \Closure(string):void */
|
||||
private static $includeFile;
|
||||
|
||||
/** @var string|null */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array<string, list<string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* List of PSR-0 prefixes
|
||||
*
|
||||
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||
*
|
||||
* @var array<string, array<string, list<string>>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var list<string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var string|null */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var array<string, self>
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param string|null $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
self::initializeIncludeClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, list<string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string> Array of classname => path
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $classMap Class to filename map
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
$paths = (array) $paths;
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
$paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
$paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param list<string>|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param list<string>|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
|
||||
if (null !== $this->vendorDir) {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
$includeFile = self::$includeFile;
|
||||
$includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||
*
|
||||
* @return array<string, self>
|
||||
*/
|
||||
public static function getRegisteredLoaders()
|
||||
{
|
||||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function initializeIncludeClosure()
|
||||
{
|
||||
if (self::$includeFile !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
*/
|
||||
self::$includeFile = \Closure::bind(static function($file) {
|
||||
include $file;
|
||||
}, null, null);
|
||||
}
|
||||
}
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\Semver\VersionParser;
|
||||
|
||||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||
*
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackages()
|
||||
{
|
||||
$packages = array();
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
||||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package satisfies a version constraint
|
||||
*
|
||||
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||
*
|
||||
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||
*
|
||||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
{
|
||||
$constraint = $parser->parseConstraints((string) $constraint);
|
||||
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||
|
||||
return $provided->matches($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||
*
|
||||
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||
* whether a given version of a package is installed, and not just whether it exists
|
||||
*
|
||||
* @param string $packageName
|
||||
* @return string Version constraint usable with composer/semver
|
||||
*/
|
||||
public static function getVersionRanges($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ranges = array();
|
||||
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||
}
|
||||
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||
}
|
||||
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||
}
|
||||
|
||||
return implode(' || ', $ranges);
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||
*/
|
||||
public static function getPrettyVersion($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['pretty_version'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||
*/
|
||||
public static function getReference($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $installed['versions'][$packageName]['reference'];
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
$installed = self::getInstalled();
|
||||
|
||||
return $installed[0]['root'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
* This is only useful for complex integrations in which a project needs to use
|
||||
* this class but then also needs to execute another project's autoloader in process,
|
||||
* and wants to ensure both projects have access to their version of installed.php.
|
||||
*
|
||||
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||
* the data it needs from this class, then call reload() with
|
||||
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||
* the project in which it runs can then also use this class safely, without
|
||||
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||
*
|
||||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
if (null === self::$canGetVendors) {
|
||||
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require __DIR__ . '/installed.php';
|
||||
self::$installed = $required;
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'dc1275c308c5b416beb314b6317daca2' => $vendorDir . '/overtrue/pinyin/src/const.php',
|
||||
);
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Overtrue\\Pinyin\\' => array($vendorDir . '/overtrue/pinyin/src'),
|
||||
);
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit7f036e4555c1f5c49b96f869c5b4f1bf
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit7f036e4555c1f5c49b96f869c5b4f1bf', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit7f036e4555c1f5c49b96f869c5b4f1bf', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf
|
||||
{
|
||||
public static $files = array (
|
||||
'dc1275c308c5b416beb314b6317daca2' => __DIR__ . '/..' . '/overtrue/pinyin/src/const.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'O' =>
|
||||
array (
|
||||
'Overtrue\\Pinyin\\' => 16,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Overtrue\\Pinyin\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/overtrue/pinyin/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit7f036e4555c1f5c49b96f869c5b4f1bf::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "overtrue/pinyin",
|
||||
"version": "4.1.0",
|
||||
"version_normalized": "4.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/overtrue/pinyin.git",
|
||||
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/overtrue/pinyin/zipball/4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
|
||||
"reference": "4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"phpunit/phpunit": "~8.0"
|
||||
},
|
||||
"time": "2023-04-27T10:17:12+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-push": [
|
||||
"composer test",
|
||||
"composer check-style"
|
||||
],
|
||||
"pre-commit": [
|
||||
"composer test",
|
||||
"composer fix-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/const.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Overtrue\\Pinyin\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com",
|
||||
"homepage": "http://github.com/overtrue"
|
||||
}
|
||||
],
|
||||
"description": "Chinese to pinyin translator.",
|
||||
"homepage": "https://github.com/overtrue/pinyin",
|
||||
"keywords": [
|
||||
"Chinese",
|
||||
"Pinyin",
|
||||
"cn2pinyin"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/overtrue/pinyin/issues",
|
||||
"source": "https://github.com/overtrue/pinyin/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../overtrue/pinyin"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
"dev-package-names": []
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => '__root__',
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => '1.0.0+no-version-set',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => NULL,
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'overtrue/pinyin' => array(
|
||||
'pretty_version' => '4.1.0',
|
||||
'version' => '4.1.0.0',
|
||||
'reference' => '4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../overtrue/pinyin',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70100)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.1.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: overtrue
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
custom: # Replace with a single custom sponsorship URL
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: composer
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "21:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: phpunit/phpunit
|
||||
versions:
|
||||
- ">= 8.a, < 9"
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 安正超
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+130
@@ -0,0 +1,130 @@
|
||||
<h1 align="center">Pinyin</h1>
|
||||
|
||||
<p align="center">
|
||||
|
||||
[](https://travis-ci.org/overtrue/pinyin)
|
||||
[](https://packagist.org/packages/overtrue/pinyin) [](https://packagist.org/packages/overtrue/pinyin) [](https://packagist.org/packages/overtrue/pinyin) [](https://packagist.org/packages/overtrue/pinyin)
|
||||
[](https://scrutinizer-ci.com/g/overtrue/pinyin/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/overtrue/pinyin/?branch=master)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fovertrue%2Fpinyin?ref=badge_shield)
|
||||
|
||||
</p>
|
||||
|
||||
:cn: 基于 [CC-CEDICT](http://cc-cedict.org/wiki/) 词典的中文转拼音工具,更准确的支持多音字的汉字转拼音解决方案。
|
||||
|
||||
|
||||
## 安装
|
||||
|
||||
使用 Composer 安装:
|
||||
|
||||
```
|
||||
$ composer require "overtrue/pinyin:~4.0"
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
可选转换方案:
|
||||
|
||||
- 内存型,适用于服务器内存空间较富余,优点:转换快
|
||||
- 小内存型(默认),适用于内存比较紧张的环境,优点:占用内存小,转换不如内存型快
|
||||
- I/O型,适用于虚拟机,内存限制比较严格环境。优点:非常微小内存消耗。缺点:转换慢,不如内存型转换快,php >= 5.5
|
||||
|
||||
## 可用选项:
|
||||
|
||||
| 选项 | 描述 |
|
||||
| ------------- | ---------------------------------------------------|
|
||||
| `PINYIN_TONE` | UNICODE 式音调:`měi hǎo` |
|
||||
| `PINYIN_ASCII_TONE` | 带数字式音调: `mei3 hao3` |
|
||||
| `PINYIN_NO_TONE` | 无音调:`mei hao` |
|
||||
| `PINYIN_KEEP_NUMBER` | 保留数字 |
|
||||
| `PINYIN_KEEP_ENGLISH` | 保留英文 |
|
||||
| `PINYIN_KEEP_PUNCTUATION` | 保留标点 |
|
||||
| `PINYIN_UMLAUT_V` | 使用 `v` 代替 `yu`, 例如:吕 `lyu` 将会转为 `lv` |
|
||||
|
||||
### 拼音数组
|
||||
|
||||
```php
|
||||
use Overtrue\Pinyin\Pinyin;
|
||||
|
||||
// 小内存型
|
||||
$pinyin = new Pinyin(); // 默认
|
||||
// 内存型
|
||||
// $pinyin = new Pinyin('\\Overtrue\\Pinyin\\MemoryFileDictLoader');
|
||||
// I/O型
|
||||
// $pinyin = new Pinyin('\\Overtrue\\Pinyin\\GeneratorFileDictLoader');
|
||||
|
||||
$pinyin->convert('带着希望去旅行,比到达终点更美好');
|
||||
// ["dai", "zhe", "xi", "wang", "qu", "lyu", "xing", "bi", "dao", "da", "zhong", "dian", "geng", "mei", "hao"]
|
||||
|
||||
$pinyin->convert('带着希望去旅行,比到达终点更美好', PINYIN_TONE);
|
||||
// ["dài","zhe","xī","wàng","qù","lǚ","xíng","bǐ","dào","dá","zhōng","diǎn","gèng","měi","hǎo"]
|
||||
|
||||
$pinyin->convert('带着希望去旅行,比到达终点更美好', PINYIN_ASCII_TONE);
|
||||
//["dai4","zhe","xi1","wang4","qu4","lyu3","xing2","bi3","dao4","da2","zhong1","dian3","geng4","mei3","hao3"]
|
||||
```
|
||||
|
||||
- 小内存型: 将字典分片载入内存
|
||||
- 内存型: 将所有字典预先载入内存
|
||||
- I/O型: 不载入内存,将字典使用文件流打开逐行遍历并运用php5.5生成器(yield)特性分配单行内存
|
||||
|
||||
|
||||
### 生成用于链接的拼音字符串
|
||||
|
||||
```php
|
||||
$pinyin->permalink('带着希望去旅行'); // dai-zhe-xi-wang-qu-lyu-xing
|
||||
$pinyin->permalink('带着希望去旅行', '.'); // dai.zhe.xi.wang.qu.lyu.xing
|
||||
```
|
||||
|
||||
### 获取首字符字符串
|
||||
|
||||
```php
|
||||
$pinyin->abbr('带着希望去旅行'); // dzxwqlx
|
||||
$pinyin->abbr('带着希望去旅行', '-'); // d-z-x-w-q-l-x
|
||||
|
||||
$pinyin->abbr('你好2018!', PINYIN_KEEP_NUMBER); // nh2018
|
||||
$pinyin->abbr('Happy New Year! 2018!', PINYIN_KEEP_ENGLISH); // HNY2018
|
||||
```
|
||||
|
||||
### 翻译整段文字为拼音
|
||||
|
||||
将会保留中文字符:`,。 ! ? : “ ” ‘ ’` 并替换为对应的英文符号。
|
||||
|
||||
```php
|
||||
$pinyin->sentence('带着希望去旅行,比到达终点更美好!');
|
||||
// dai zhe xi wang qu lyu xing, bi dao da zhong dian geng mei hao!
|
||||
|
||||
$pinyin->sentence('带着希望去旅行,比到达终点更美好!', PINYIN_TONE);
|
||||
// dài zhe xī wàng qù lǚ xíng, bǐ dào dá zhōng diǎn gèng měi hǎo!
|
||||
```
|
||||
|
||||
### 翻译姓名
|
||||
|
||||
姓名的姓的读音有些与普通字不一样,比如 ‘单’ 常见的音为 `dan`,而作为姓的时候读 `shan`。
|
||||
|
||||
```php
|
||||
$pinyin->name('单某某'); // ['shan', 'mou', 'mou']
|
||||
$pinyin->name('单某某', PINYIN_TONE); // ["shàn","mǒu","mǒu"]
|
||||
```
|
||||
|
||||
更多使用请参考 [测试用例](https://github.com/overtrue/pinyin/blob/master/tests/AbstractDictLoaderTestCase.php)。
|
||||
|
||||
## 在 Laravel 中使用
|
||||
|
||||
独立的包在这里:[overtrue/laravel-pinyin](https://github.com/overtrue/laravel-pinyin)
|
||||
|
||||
## Contribution
|
||||
欢迎提意见及完善补充词库 [`overtrue/pinyin-dictionary-maker`](https://github.com/overtrue/pinyin-dictionary-maker/tree/master/patches) :kiss:
|
||||
|
||||
## 参考
|
||||
|
||||
- [详细参考资料](https://github.com/overtrue/pinyin-resources)
|
||||
|
||||
## PHP 扩展包开发
|
||||
|
||||
> 想知道如何从零开始构建 PHP 扩展包?
|
||||
>
|
||||
> 请关注我的实战课程,我会在此课程中分享一些扩展开发经验 —— [《PHP 扩展包实战教程 - 从入门到发布》](https://learnku.com/courses/creating-package)
|
||||
|
||||
# License
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fovertrue%2Fpinyin?ref=badge_large)
|
||||
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "overtrue/pinyin",
|
||||
"description": "Chinese to pinyin translator.",
|
||||
"keywords": [
|
||||
"chinese",
|
||||
"pinyin",
|
||||
"cn2pinyin"
|
||||
],
|
||||
"homepage": "https://github.com/overtrue/pinyin",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"homepage": "http://github.com/overtrue",
|
||||
"email": "anzhengchao@gmail.com"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\Pinyin\\": "src/"
|
||||
},
|
||||
"files": ["src/const.php"]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Overtrue\\Pinyin\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php":">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~8.0",
|
||||
"brainmaestro/composer-git-hooks": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^2.16"
|
||||
},
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-commit": [
|
||||
"composer test",
|
||||
"composer fix-style"
|
||||
],
|
||||
"pre-push": [
|
||||
"composer test",
|
||||
"composer check-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-update-cmd": [
|
||||
"cghooks update"
|
||||
],
|
||||
"post-merge": "composer install",
|
||||
"post-install-cmd": [
|
||||
"cghooks add --ignore-lock",
|
||||
"cghooks update"
|
||||
],
|
||||
"cghooks": "vendor/bin/cghooks",
|
||||
"check-style": "php-cs-fixer fix --using-cache=no --diff --config=.php_cs --dry-run --ansi",
|
||||
"fix-style": "php-cs-fixer fix --using-cache=no --config=.php_cs --ansi",
|
||||
"test": "vendor/bin/phpunit --colors=always"
|
||||
},
|
||||
"scripts-descriptions": {
|
||||
"test": "Run all tests.",
|
||||
"check-style": "Run style checks (only dry run - no fixing!).",
|
||||
"fix-style": "Run style checks and fix violations."
|
||||
}
|
||||
}
|
||||
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
return array (
|
||||
'万俟' => ' mò qí',
|
||||
'尉迟' => ' yù chí',
|
||||
'单于' => ' chán yú',
|
||||
'不' => ' fǒu',
|
||||
'沈' => ' shěn',
|
||||
'称' => ' chēng',
|
||||
'车' => ' chē',
|
||||
'万' => ' wàn',
|
||||
'汤' => ' tāng',
|
||||
'阿' => ' ā',
|
||||
'丁' => ' dīng',
|
||||
'强' => ' qiáng',
|
||||
'仇' => ' qiú',
|
||||
'叶' => ' yè',
|
||||
'阚' => ' kàn',
|
||||
'乐' => ' yuè',
|
||||
'乜' => ' niè',
|
||||
'陆' => ' lù',
|
||||
'殷' => ' yīn',
|
||||
'牟' => ' móu',
|
||||
'区' => ' ōu',
|
||||
'宿' => ' sù',
|
||||
'俞' => ' yú',
|
||||
'余' => ' yú',
|
||||
'齐' => ' qí',
|
||||
'许' => ' xǔ',
|
||||
'信' => ' xìn',
|
||||
'无' => ' wú',
|
||||
'浣' => ' wǎn',
|
||||
'艾' => ' ài',
|
||||
'浅' => ' qiǎn',
|
||||
'烟' => ' yān',
|
||||
'蓝' => ' lán',
|
||||
'於' => ' yú',
|
||||
'寻' => ' xún',
|
||||
'殳' => ' shū',
|
||||
'思' => ' sī',
|
||||
'鸟' => ' niǎo',
|
||||
'卜' => ' bǔ',
|
||||
'单' => ' shàn',
|
||||
'南' => ' nán',
|
||||
'柏' => ' bǎi',
|
||||
'朴' => ' piáo',
|
||||
'繁' => ' pó',
|
||||
'曾' => ' zēng',
|
||||
'瞿' => ' qú',
|
||||
'缪' => ' miào',
|
||||
'石' => ' shí',
|
||||
'冯' => ' féng',
|
||||
'覃' => ' qín',
|
||||
'幺' => ' yāo',
|
||||
'种' => ' chóng',
|
||||
'折' => ' shè',
|
||||
'燕' => ' yān',
|
||||
'纪' => ' jǐ',
|
||||
'过' => ' guō',
|
||||
'华' => ' huà',
|
||||
'冼' => ' xiǎn',
|
||||
'秘' => ' bì',
|
||||
'重' => ' chóng',
|
||||
'解' => ' xiè',
|
||||
'那' => ' nā',
|
||||
'和' => ' hé',
|
||||
'贾' => ' jiǎ',
|
||||
'塔' => ' tǎ',
|
||||
'盛' => ' shèng',
|
||||
'查' => ' zhā',
|
||||
'盖' => ' gě',
|
||||
'居' => ' jū',
|
||||
'哈' => ' hǎ',
|
||||
'的' => ' dē',
|
||||
'薄' => ' bó',
|
||||
'佴' => ' nài',
|
||||
'六' => ' lù',
|
||||
'都' => ' dū',
|
||||
'翟' => ' zhái',
|
||||
'扎' => ' zā',
|
||||
'藏' => ' zàng',
|
||||
'粘' => ' niàn',
|
||||
'难' => ' nàn',
|
||||
'若' => ' ruò',
|
||||
'貟' => ' yùn',
|
||||
'贠' => ' yùn',
|
||||
);
|
||||
Vendored
+8003
File diff suppressed because it is too large
Load Diff
Vendored
+8003
File diff suppressed because it is too large
Load Diff
Vendored
+8003
File diff suppressed because it is too large
Load Diff
Vendored
+8003
File diff suppressed because it is too large
Load Diff
Vendored
+8003
File diff suppressed because it is too large
Load Diff
Vendored
+2055
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\Pinyin;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* Dict loader interface.
|
||||
*/
|
||||
interface DictLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Load dict.
|
||||
*
|
||||
* <pre>
|
||||
* [
|
||||
* '响应时间' => "[\t]xiǎng[\t]yìng[\t]shí[\t]jiān",
|
||||
* '长篇连载' => '[\t]cháng[\t]piān[\t]lián[\t]zǎi',
|
||||
* //...
|
||||
* ]
|
||||
* </pre>
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function map(Closure $callback);
|
||||
|
||||
/**
|
||||
* Load surname dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function mapSurname(Closure $callback);
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\Pinyin;
|
||||
|
||||
use Closure;
|
||||
|
||||
class FileDictLoader implements DictLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Words segment name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $segmentName = 'words_%s';
|
||||
|
||||
/**
|
||||
* Dict path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function map(Closure $callback)
|
||||
{
|
||||
for ($i = 0; $i < 100; ++$i) {
|
||||
$segment = $this->path . '/' . sprintf($this->segmentName, $i);
|
||||
|
||||
if (file_exists($segment)) {
|
||||
$dictionary = (array) include $segment;
|
||||
$callback($dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load surname dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function mapSurname(Closure $callback)
|
||||
{
|
||||
$surnames = $this->path . '/surnames';
|
||||
|
||||
if (file_exists($surnames)) {
|
||||
$dictionary = (array) include $surnames;
|
||||
$callback($dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\Pinyin;
|
||||
|
||||
use Closure;
|
||||
use SplFileObject;
|
||||
use Generator;
|
||||
|
||||
class GeneratorFileDictLoader implements DictLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Data directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Words segment name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $segmentName = 'words_%s';
|
||||
|
||||
/**
|
||||
* SplFileObjects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $handles = [];
|
||||
|
||||
/**
|
||||
* surnames.
|
||||
*
|
||||
* @var SplFileObject
|
||||
*/
|
||||
protected static $surnamesHandle;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
for ($i = 0; $i < 100; ++$i) {
|
||||
$segment = $this->path . '/' . sprintf($this->segmentName, $i);
|
||||
|
||||
if (file_exists($segment) && is_file($segment)) {
|
||||
array_push(static::$handles, $this->openFile($segment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new file object.
|
||||
*
|
||||
* @param string $filename file path
|
||||
* @param string $mode file open mode
|
||||
*
|
||||
* @return SplFileObject
|
||||
*/
|
||||
protected function openFile($filename, $mode = 'r')
|
||||
{
|
||||
return new SplFileObject($filename, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Generator syntax.
|
||||
*
|
||||
* @param array $handles SplFileObjects
|
||||
*
|
||||
* @return Generator
|
||||
*/
|
||||
protected function getGenerator(array $handles)
|
||||
{
|
||||
foreach ($handles as $handle) {
|
||||
$handle->seek(0);
|
||||
while (false === $handle->eof()) {
|
||||
$string = str_replace(['\'', ' ', PHP_EOL, ','], '', $handle->fgets());
|
||||
|
||||
if (false === strpos($string, '=>')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($string, $pinyin) = explode('=>', $string);
|
||||
|
||||
yield $string => $pinyin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the stream.
|
||||
*
|
||||
* @param Generator $generator
|
||||
* @param Closure $callback
|
||||
*
|
||||
* @author Seven Du <shiweidu@outlook.com>
|
||||
*/
|
||||
protected function traversing(Generator $generator, Closure $callback)
|
||||
{
|
||||
foreach ($generator as $string => $pinyin) {
|
||||
$callback([$string => $pinyin]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function map(Closure $callback)
|
||||
{
|
||||
$this->traversing($this->getGenerator(static::$handles), $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load surname dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function mapSurname(Closure $callback)
|
||||
{
|
||||
if (!static::$surnamesHandle instanceof SplFileObject) {
|
||||
static::$surnamesHandle = $this->openFile($this->path . '/surnames');
|
||||
}
|
||||
|
||||
$this->traversing($this->getGenerator([static::$surnamesHandle]), $callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\Pinyin;
|
||||
|
||||
use Closure;
|
||||
|
||||
class MemoryFileDictLoader implements DictLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Data directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Words segment name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $segmentName = 'words_%s';
|
||||
|
||||
/**
|
||||
* Segment files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $segments = [];
|
||||
|
||||
/**
|
||||
* Surname cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $surnames = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
for ($i = 0; $i < 100; ++$i) {
|
||||
$segment = $path . '/' . sprintf($this->segmentName, $i);
|
||||
|
||||
if (file_exists($segment)) {
|
||||
$this->segments[] = (array) include $segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function map(Closure $callback)
|
||||
{
|
||||
foreach ($this->segments as $dictionary) {
|
||||
$callback($dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load surname dict.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*/
|
||||
public function mapSurname(Closure $callback)
|
||||
{
|
||||
if (empty($this->surnames)) {
|
||||
$surnames = $this->path . '/surnames';
|
||||
|
||||
if (file_exists($surnames)) {
|
||||
$this->surnames = (array) include $surnames;
|
||||
}
|
||||
}
|
||||
|
||||
$callback($this->surnames);
|
||||
}
|
||||
}
|
||||
+343
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Overtrue\Pinyin;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Pinyin
|
||||
{
|
||||
/**
|
||||
* Dict loader.
|
||||
*
|
||||
* @var \Overtrue\Pinyin\DictLoaderInterface
|
||||
*/
|
||||
protected $loader;
|
||||
|
||||
/**
|
||||
* Punctuations map.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $punctuations = [
|
||||
',' => ',',
|
||||
'。' => '.',
|
||||
'!' => '!',
|
||||
'?' => '?',
|
||||
':' => ':',
|
||||
'“' => '"',
|
||||
'”' => '"',
|
||||
'‘' => "'",
|
||||
'’' => "'",
|
||||
'_' => '_',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $loaderName
|
||||
*/
|
||||
public function __construct($loaderName = null)
|
||||
{
|
||||
$this->loader = $loaderName ?: 'Overtrue\\Pinyin\\FileDictLoader';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string to pinyin.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $option
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function convert($string, $option = PINYIN_DEFAULT)
|
||||
{
|
||||
$pinyin = $this->romanize($string, $option);
|
||||
|
||||
return $this->splitWords($pinyin, $option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string (person name) to pinyin.
|
||||
*
|
||||
* @param string $stringName
|
||||
* @param int $option
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function name($stringName, $option = PINYIN_NAME)
|
||||
{
|
||||
$option = $option | PINYIN_NAME;
|
||||
|
||||
$pinyin = $this->romanize($stringName, $option);
|
||||
|
||||
return $this->splitWords($pinyin, $option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pinyin permalink from string.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $delimiter
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function permalink($string, $delimiter = '-', $option = PINYIN_DEFAULT)
|
||||
{
|
||||
if (\is_int($delimiter)) {
|
||||
list($option, $delimiter) = [$delimiter, '-'];
|
||||
}
|
||||
|
||||
if (!in_array($delimiter, ['_', '-', '.', ''], true)) {
|
||||
throw new InvalidArgumentException("Delimiter must be one of: '_', '-', '', '.'.");
|
||||
}
|
||||
|
||||
return implode($delimiter, $this->convert($string, $option | \PINYIN_KEEP_NUMBER | \PINYIN_KEEP_ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return first letters.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $delimiter
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function abbr($string, $delimiter = '', $option = PINYIN_DEFAULT)
|
||||
{
|
||||
if (\is_int($delimiter)) {
|
||||
list($option, $delimiter) = [$delimiter, ''];
|
||||
}
|
||||
|
||||
return implode($delimiter, array_map(function ($pinyin) {
|
||||
return \is_numeric($pinyin) || preg_match('/\d+/', $pinyin) ? $pinyin : mb_substr($pinyin, 0, 1);
|
||||
}, $this->convert($string, $option | PINYIN_NO_TONE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Chinese phrase to pinyin.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $delimiter
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function phrase($string, $delimiter = ' ', $option = PINYIN_DEFAULT)
|
||||
{
|
||||
if (\is_int($delimiter)) {
|
||||
list($option, $delimiter) = [$delimiter, ' '];
|
||||
}
|
||||
|
||||
return implode($delimiter, $this->convert($string, $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* Chinese to pinyin sentence.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $delimiter
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function sentence($string, $delimiter = ' ', $option = \PINYIN_NO_TONE)
|
||||
{
|
||||
if (\is_int($delimiter)) {
|
||||
list($option, $delimiter) = [$delimiter, ' '];
|
||||
}
|
||||
|
||||
return implode($delimiter, $this->convert($string, $option | \PINYIN_KEEP_PUNCTUATION | \PINYIN_KEEP_ENGLISH | \PINYIN_KEEP_NUMBER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loader setter.
|
||||
*
|
||||
* @param \Overtrue\Pinyin\DictLoaderInterface $loader
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLoader(DictLoaderInterface $loader)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return dict loader,.
|
||||
*
|
||||
* @return \Overtrue\Pinyin\DictLoaderInterface
|
||||
*/
|
||||
public function getLoader()
|
||||
{
|
||||
if (!($this->loader instanceof DictLoaderInterface)) {
|
||||
$dataDir = dirname(__DIR__) . '/data/';
|
||||
|
||||
$loaderName = $this->loader;
|
||||
$this->loader = new $loaderName($dataDir);
|
||||
}
|
||||
|
||||
return $this->loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Chinese to pinyin.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function romanize($string, $option = \PINYIN_DEFAULT)
|
||||
{
|
||||
$string = $this->prepare($string, $option);
|
||||
|
||||
$dictLoader = $this->getLoader();
|
||||
|
||||
if ($this->hasOption($option, \PINYIN_NAME)) {
|
||||
$string = $this->convertSurname($string, $dictLoader);
|
||||
}
|
||||
|
||||
$dictLoader->map(function ($dictionary) use (&$string) {
|
||||
$string = strtr($string, $dictionary);
|
||||
});
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Chinese Surname to pinyin.
|
||||
*
|
||||
* @param string $string
|
||||
* @param \Overtrue\Pinyin\DictLoaderInterface $dictLoader
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function convertSurname($string, $dictLoader)
|
||||
{
|
||||
$dictLoader->mapSurname(function ($dictionary) use (&$string) {
|
||||
foreach ($dictionary as $surname => $pinyin) {
|
||||
if (0 === strpos($string, $surname)) {
|
||||
$string = $pinyin . mb_substr($string, mb_strlen($surname, 'UTF-8'), mb_strlen($string, 'UTF-8') - 1, 'UTF-8');
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split pinyin string to words.
|
||||
*
|
||||
* @param string $pinyin
|
||||
* @param string $option
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function splitWords($pinyin, $option)
|
||||
{
|
||||
$split = array_filter(preg_split('/\s+/i', $pinyin));
|
||||
|
||||
if (!$this->hasOption($option, PINYIN_TONE)) {
|
||||
foreach ($split as $index => $pinyin) {
|
||||
$split[$index] = $this->formatTone($pinyin, $option);
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($split);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $option
|
||||
* @param int $check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasOption($option, $check)
|
||||
{
|
||||
return ($option & $check) === $check;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-process.
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function prepare($string, $option = \PINYIN_DEFAULT)
|
||||
{
|
||||
$string = preg_replace_callback('~[a-z0-9_-]+~i', function ($matches) {
|
||||
return "\t" . $matches[0];
|
||||
}, $string);
|
||||
|
||||
$regex = ['\x{3007}\x{2E80}-\x{2FFF}\x{3100}-\x{312F}\x{31A0}-\x{31EF}\x{3400}-\x{4DBF}\x{4E00}-\x{9FFF}\x{F900}-\x{FAFF}', '\p{Z}', '\p{M}', "\t"];
|
||||
|
||||
if ($this->hasOption($option, \PINYIN_KEEP_NUMBER)) {
|
||||
\array_push($regex, '0-9');
|
||||
}
|
||||
|
||||
if ($this->hasOption($option, \PINYIN_KEEP_ENGLISH)) {
|
||||
\array_push($regex, 'a-zA-Z');
|
||||
}
|
||||
|
||||
if ($this->hasOption($option, \PINYIN_KEEP_PUNCTUATION)) {
|
||||
$punctuations = array_merge($this->punctuations, ["\t" => ' ', ' ' => ' ']);
|
||||
$string = trim(str_replace(array_keys($punctuations), $punctuations, $string));
|
||||
|
||||
\array_push($regex, preg_quote(implode(array_merge(array_keys($this->punctuations), $this->punctuations)), '~'));
|
||||
}
|
||||
|
||||
return preg_replace(\sprintf('~[^%s]~u', implode($regex)), '', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format.
|
||||
*
|
||||
* @param string $pinyin
|
||||
* @param int $option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTone($pinyin, $option = \PINYIN_NO_TONE)
|
||||
{
|
||||
$replacements = [
|
||||
// mb_chr(593) => 'ɑ' 轻声中除了 `ɑ` 和 `ü` 以外,其它和字母一样
|
||||
'ɑ' => ['a', 5], 'ü' => ['yu', 5],
|
||||
'üē' => ['ue', 1], 'üé' => ['ue', 2], 'üě' => ['ue', 3], 'üè' => ['ue', 4],
|
||||
'ā' => ['a', 1], 'ē' => ['e', 1], 'ī' => ['i', 1], 'ō' => ['o', 1], 'ū' => ['u', 1], 'ǖ' => ['yu', 1],
|
||||
'á' => ['a', 2], 'é' => ['e', 2], 'í' => ['i', 2], 'ó' => ['o', 2], 'ú' => ['u', 2], 'ǘ' => ['yu', 2],
|
||||
'ǎ' => ['a', 3], 'ě' => ['e', 3], 'ǐ' => ['i', 3], 'ǒ' => ['o', 3], 'ǔ' => ['u', 3], 'ǚ' => ['yu', 3],
|
||||
'à' => ['a', 4], 'è' => ['e', 4], 'ì' => ['i', 4], 'ò' => ['o', 4], 'ù' => ['u', 4], 'ǜ' => ['yu', 4],
|
||||
];
|
||||
|
||||
foreach ($replacements as $unicode => $replacement) {
|
||||
if (false !== strpos($pinyin, $unicode)) {
|
||||
$umlaut = $replacement[0];
|
||||
|
||||
// https://zh.wikipedia.org/wiki/%C3%9C
|
||||
if ($this->hasOption($option, \PINYIN_UMLAUT_V) && 'yu' == $umlaut) {
|
||||
$umlaut = 'v';
|
||||
}
|
||||
|
||||
$pinyin = str_replace($unicode, $umlaut, $pinyin) . ($this->hasOption($option, PINYIN_ASCII_TONE) ? $replacement[1] : '');
|
||||
}
|
||||
}
|
||||
|
||||
return $pinyin;
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the overtrue/pinyin.
|
||||
*
|
||||
* (c) overtrue <i@overtrue.me>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
define('PINYIN_DEFAULT', 4096);
|
||||
define('PINYIN_TONE', 2);
|
||||
define('PINYIN_NO_TONE', 4);
|
||||
define('PINYIN_ASCII_TONE', 8);
|
||||
define('PINYIN_NAME', 16);
|
||||
define('PINYIN_KEEP_NUMBER', 32);
|
||||
define('PINYIN_KEEP_ENGLISH', 64);
|
||||
define('PINYIN_UMLAUT_V', 128);
|
||||
define('PINYIN_KEEP_PUNCTUATION', 256);
|
||||
Reference in New Issue
Block a user