ajout admin panel
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* added `$useNaturalSort` argument to `Finder::sortByName()`
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* added $useNaturalSort option to Finder::sortByName() method
|
||||
* the `Finder::sortByName()` method will have a new `$useNaturalSort`
|
||||
argument in version 5.0, not defining it is deprecated
|
||||
* added `Finder::reverseSorting()` to reverse the sorting
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* removed `ExceptionInterface`
|
||||
* removed `Symfony\Component\Finder\Iterator\FilterIterator`
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
|
||||
* added Finder::hasResults() method to check if any results were found
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* added double-star matching to Glob::toRegex()
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
* removed deprecated classes
|
||||
|
||||
2.8.0
|
||||
-----
|
||||
|
||||
* deprecated adapters and related classes
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
* added support for GLOB_BRACE in the paths passed to Finder::in()
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs())
|
||||
* unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* added Finder::path() and Finder::notPath() methods
|
||||
* added finder adapters to improve performance on specific platforms
|
||||
* added support for wildcard characters (glob patterns) in the paths passed
|
||||
to Finder::in()
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and
|
||||
Finder::sortByModifiedTime()
|
||||
* added Countable to Finder
|
||||
* added support for an array of directories as an argument to
|
||||
Finder::exclude()
|
||||
* added searching based on the file content via Finder::contains() and
|
||||
Finder::notContains()
|
||||
* added support for the != operator in the Comparator
|
||||
* [BC BREAK] filter expressions (used for file name and content) are no more
|
||||
considered as regexps but glob patterns when they are enclosed in '*' or '?'
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Comparator;
|
||||
|
||||
/**
|
||||
* Comparator.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Comparator
|
||||
{
|
||||
private $target;
|
||||
private $operator = '==';
|
||||
|
||||
/**
|
||||
* Gets the target value.
|
||||
*
|
||||
* @return string The target value
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
public function setTarget(string $target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the comparison operator.
|
||||
*
|
||||
* @return string The operator
|
||||
*/
|
||||
public function getOperator()
|
||||
{
|
||||
return $this->operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the comparison operator.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setOperator(string $operator)
|
||||
{
|
||||
if ('' === $operator) {
|
||||
$operator = '==';
|
||||
}
|
||||
|
||||
if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
|
||||
}
|
||||
|
||||
$this->operator = $operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests against the target.
|
||||
*
|
||||
* @param mixed $test A test value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function test($test)
|
||||
{
|
||||
switch ($this->operator) {
|
||||
case '>':
|
||||
return $test > $this->target;
|
||||
case '>=':
|
||||
return $test >= $this->target;
|
||||
case '<':
|
||||
return $test < $this->target;
|
||||
case '<=':
|
||||
return $test <= $this->target;
|
||||
case '!=':
|
||||
return $test != $this->target;
|
||||
}
|
||||
|
||||
return $test == $this->target;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Comparator;
|
||||
|
||||
/**
|
||||
* DateCompare compiles date comparisons.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DateComparator extends Comparator
|
||||
{
|
||||
/**
|
||||
* @param string $test A comparison string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the test is not understood
|
||||
*/
|
||||
public function __construct(string $test)
|
||||
{
|
||||
if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
|
||||
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
|
||||
}
|
||||
|
||||
try {
|
||||
$date = new \DateTime($matches[2]);
|
||||
$target = $date->format('U');
|
||||
} catch (\Exception $e) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
|
||||
}
|
||||
|
||||
$operator = isset($matches[1]) ? $matches[1] : '==';
|
||||
if ('since' === $operator || 'after' === $operator) {
|
||||
$operator = '>';
|
||||
}
|
||||
|
||||
if ('until' === $operator || 'before' === $operator) {
|
||||
$operator = '<';
|
||||
}
|
||||
|
||||
$this->setOperator($operator);
|
||||
$this->setTarget($target);
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Comparator;
|
||||
|
||||
/**
|
||||
* NumberComparator compiles a simple comparison to an anonymous
|
||||
* subroutine, which you can call with a value to be tested again.
|
||||
*
|
||||
* Now this would be very pointless, if NumberCompare didn't understand
|
||||
* magnitudes.
|
||||
*
|
||||
* The target value may use magnitudes of kilobytes (k, ki),
|
||||
* megabytes (m, mi), or gigabytes (g, gi). Those suffixed
|
||||
* with an i use the appropriate 2**n version in accordance with the
|
||||
* IEC standard: http://physics.nist.gov/cuu/Units/binary.html
|
||||
*
|
||||
* Based on the Perl Number::Compare module.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com> PHP port
|
||||
* @author Richard Clamp <richardc@unixbeard.net> Perl version
|
||||
* @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
|
||||
* @copyright 2002 Richard Clamp <richardc@unixbeard.net>
|
||||
*
|
||||
* @see http://physics.nist.gov/cuu/Units/binary.html
|
||||
*/
|
||||
class NumberComparator extends Comparator
|
||||
{
|
||||
/**
|
||||
* @param string|int $test A comparison string or an integer
|
||||
*
|
||||
* @throws \InvalidArgumentException If the test is not understood
|
||||
*/
|
||||
public function __construct(?string $test)
|
||||
{
|
||||
if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
|
||||
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
|
||||
}
|
||||
|
||||
$target = $matches[2];
|
||||
if (!is_numeric($target)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
|
||||
}
|
||||
if (isset($matches[3])) {
|
||||
// magnitude
|
||||
switch (strtolower($matches[3])) {
|
||||
case 'k':
|
||||
$target *= 1000;
|
||||
break;
|
||||
case 'ki':
|
||||
$target *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
$target *= 1000000;
|
||||
break;
|
||||
case 'mi':
|
||||
$target *= 1024 * 1024;
|
||||
break;
|
||||
case 'g':
|
||||
$target *= 1000000000;
|
||||
break;
|
||||
case 'gi':
|
||||
$target *= 1024 * 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setTarget($target);
|
||||
$this->setOperator(isset($matches[1]) ? $matches[1] : '==');
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Exception;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class AccessDeniedException extends \UnexpectedValueException
|
||||
{
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Exception;
|
||||
|
||||
/**
|
||||
* @author Andreas Erhard <andreas.erhard@i-med.ac.at>
|
||||
*/
|
||||
class DirectoryNotFoundException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,797 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder;
|
||||
|
||||
use Symfony\Component\Finder\Comparator\DateComparator;
|
||||
use Symfony\Component\Finder\Comparator\NumberComparator;
|
||||
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
|
||||
use Symfony\Component\Finder\Iterator\CustomFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
|
||||
use Symfony\Component\Finder\Iterator\SortableIterator;
|
||||
|
||||
/**
|
||||
* Finder allows to build rules to find files and directories.
|
||||
*
|
||||
* It is a thin wrapper around several specialized iterator classes.
|
||||
*
|
||||
* All rules may be invoked several times.
|
||||
*
|
||||
* All methods return the current Finder object to allow chaining:
|
||||
*
|
||||
* $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Finder implements \IteratorAggregate, \Countable
|
||||
{
|
||||
const IGNORE_VCS_FILES = 1;
|
||||
const IGNORE_DOT_FILES = 2;
|
||||
const IGNORE_VCS_IGNORED_FILES = 4;
|
||||
|
||||
private $mode = 0;
|
||||
private $names = [];
|
||||
private $notNames = [];
|
||||
private $exclude = [];
|
||||
private $filters = [];
|
||||
private $depths = [];
|
||||
private $sizes = [];
|
||||
private $followLinks = false;
|
||||
private $reverseSorting = false;
|
||||
private $sort = false;
|
||||
private $ignore = 0;
|
||||
private $dirs = [];
|
||||
private $dates = [];
|
||||
private $iterators = [];
|
||||
private $contains = [];
|
||||
private $notContains = [];
|
||||
private $paths = [];
|
||||
private $notPaths = [];
|
||||
private $ignoreUnreadableDirs = false;
|
||||
|
||||
private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Finder.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function create()
|
||||
{
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts the matching to directories only.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function directories()
|
||||
{
|
||||
$this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts the matching to files only.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
$this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tests for the directory depth.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $finder->depth('> 1') // the Finder will start matching at level 1.
|
||||
* $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
|
||||
* $finder->depth(['>= 1', '< 3'])
|
||||
*
|
||||
* @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see DepthRangeFilterIterator
|
||||
* @see NumberComparator
|
||||
*/
|
||||
public function depth($levels)
|
||||
{
|
||||
foreach ((array) $levels as $level) {
|
||||
$this->depths[] = new Comparator\NumberComparator($level);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tests for file dates (last modified).
|
||||
*
|
||||
* The date must be something that strtotime() is able to parse:
|
||||
*
|
||||
* $finder->date('since yesterday');
|
||||
* $finder->date('until 2 days ago');
|
||||
* $finder->date('> now - 2 hours');
|
||||
* $finder->date('>= 2005-10-15');
|
||||
* $finder->date(['>= 2005-10-15', '<= 2006-05-27']);
|
||||
*
|
||||
* @param string|string[] $dates A date range string or an array of date ranges
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see strtotime
|
||||
* @see DateRangeFilterIterator
|
||||
* @see DateComparator
|
||||
*/
|
||||
public function date($dates)
|
||||
{
|
||||
foreach ((array) $dates as $date) {
|
||||
$this->dates[] = new Comparator\DateComparator($date);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds rules that files must match.
|
||||
*
|
||||
* You can use patterns (delimited with / sign), globs or simple strings.
|
||||
*
|
||||
* $finder->name('*.php')
|
||||
* $finder->name('/\.php$/') // same as above
|
||||
* $finder->name('test.php')
|
||||
* $finder->name(['test.py', 'test.php'])
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilenameFilterIterator
|
||||
*/
|
||||
public function name($patterns)
|
||||
{
|
||||
$this->names = array_merge($this->names, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds rules that files must not match.
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilenameFilterIterator
|
||||
*/
|
||||
public function notName($patterns)
|
||||
{
|
||||
$this->notNames = array_merge($this->notNames, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tests that file contents must match.
|
||||
*
|
||||
* Strings or PCRE patterns can be used:
|
||||
*
|
||||
* $finder->contains('Lorem ipsum')
|
||||
* $finder->contains('/Lorem ipsum/i')
|
||||
* $finder->contains(['dolor', '/ipsum/i'])
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilecontentFilterIterator
|
||||
*/
|
||||
public function contains($patterns)
|
||||
{
|
||||
$this->contains = array_merge($this->contains, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tests that file contents must not match.
|
||||
*
|
||||
* Strings or PCRE patterns can be used:
|
||||
*
|
||||
* $finder->notContains('Lorem ipsum')
|
||||
* $finder->notContains('/Lorem ipsum/i')
|
||||
* $finder->notContains(['lorem', '/dolor/i'])
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilecontentFilterIterator
|
||||
*/
|
||||
public function notContains($patterns)
|
||||
{
|
||||
$this->notContains = array_merge($this->notContains, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds rules that filenames must match.
|
||||
*
|
||||
* You can use patterns (delimited with / sign) or simple strings.
|
||||
*
|
||||
* $finder->path('some/special/dir')
|
||||
* $finder->path('/some\/special\/dir/') // same as above
|
||||
* $finder->path(['some dir', 'another/dir'])
|
||||
*
|
||||
* Use only / as dirname separator.
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilenameFilterIterator
|
||||
*/
|
||||
public function path($patterns)
|
||||
{
|
||||
$this->paths = array_merge($this->paths, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds rules that filenames must not match.
|
||||
*
|
||||
* You can use patterns (delimited with / sign) or simple strings.
|
||||
*
|
||||
* $finder->notPath('some/special/dir')
|
||||
* $finder->notPath('/some\/special\/dir/') // same as above
|
||||
* $finder->notPath(['some/file.txt', 'another/file.log'])
|
||||
*
|
||||
* Use only / as dirname separator.
|
||||
*
|
||||
* @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see FilenameFilterIterator
|
||||
*/
|
||||
public function notPath($patterns)
|
||||
{
|
||||
$this->notPaths = array_merge($this->notPaths, (array) $patterns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tests for file sizes.
|
||||
*
|
||||
* $finder->size('> 10K');
|
||||
* $finder->size('<= 1Ki');
|
||||
* $finder->size(4);
|
||||
* $finder->size(['> 10K', '< 20K'])
|
||||
*
|
||||
* @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SizeRangeFilterIterator
|
||||
* @see NumberComparator
|
||||
*/
|
||||
public function size($sizes)
|
||||
{
|
||||
foreach ((array) $sizes as $size) {
|
||||
$this->sizes[] = new Comparator\NumberComparator($size);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes directories.
|
||||
*
|
||||
* Directories passed as argument must be relative to the ones defined with the `in()` method. For example:
|
||||
*
|
||||
* $finder->in(__DIR__)->exclude('ruby');
|
||||
*
|
||||
* @param string|array $dirs A directory path or an array of directories
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see ExcludeDirectoryFilterIterator
|
||||
*/
|
||||
public function exclude($dirs)
|
||||
{
|
||||
$this->exclude = array_merge($this->exclude, (array) $dirs);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes "hidden" directories and files (starting with a dot).
|
||||
*
|
||||
* This option is enabled by default.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see ExcludeDirectoryFilterIterator
|
||||
*/
|
||||
public function ignoreDotFiles(bool $ignoreDotFiles)
|
||||
{
|
||||
if ($ignoreDotFiles) {
|
||||
$this->ignore |= static::IGNORE_DOT_FILES;
|
||||
} else {
|
||||
$this->ignore &= ~static::IGNORE_DOT_FILES;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the finder to ignore version control directories.
|
||||
*
|
||||
* This option is enabled by default.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see ExcludeDirectoryFilterIterator
|
||||
*/
|
||||
public function ignoreVCS(bool $ignoreVCS)
|
||||
{
|
||||
if ($ignoreVCS) {
|
||||
$this->ignore |= static::IGNORE_VCS_FILES;
|
||||
} else {
|
||||
$this->ignore &= ~static::IGNORE_VCS_FILES;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces Finder to obey .gitignore and ignore files based on rules listed there.
|
||||
*
|
||||
* This option is disabled by default.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function ignoreVCSIgnored(bool $ignoreVCSIgnored)
|
||||
{
|
||||
if ($ignoreVCSIgnored) {
|
||||
$this->ignore |= static::IGNORE_VCS_IGNORED_FILES;
|
||||
} else {
|
||||
$this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds VCS patterns.
|
||||
*
|
||||
* @see ignoreVCS()
|
||||
*
|
||||
* @param string|string[] $pattern VCS patterns to ignore
|
||||
*/
|
||||
public static function addVCSPattern($pattern)
|
||||
{
|
||||
foreach ((array) $pattern as $p) {
|
||||
self::$vcsPatterns[] = $p;
|
||||
}
|
||||
|
||||
self::$vcsPatterns = array_unique(self::$vcsPatterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by an anonymous function.
|
||||
*
|
||||
* The anonymous function receives two \SplFileInfo instances to compare.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sort(\Closure $closure)
|
||||
{
|
||||
$this->sort = $closure;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by name.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sortByName(bool $useNaturalSort = false)
|
||||
{
|
||||
$this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by type (directories before files), then by name.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sortByType()
|
||||
{
|
||||
$this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by the last accessed time.
|
||||
*
|
||||
* This is the time that the file was last accessed, read or written to.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sortByAccessedTime()
|
||||
{
|
||||
$this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the sorting.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reverseSorting()
|
||||
{
|
||||
$this->reverseSorting = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by the last inode changed time.
|
||||
*
|
||||
* This is the time that the inode information was last modified (permissions, owner, group or other metadata).
|
||||
*
|
||||
* On Windows, since inode is not available, changed time is actually the file creation time.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sortByChangedTime()
|
||||
{
|
||||
$this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts files and directories by the last modified time.
|
||||
*
|
||||
* This is the last time the actual contents of the file were last modified.
|
||||
*
|
||||
* This can be slow as all the matching files and directories must be retrieved for comparison.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see SortableIterator
|
||||
*/
|
||||
public function sortByModifiedTime()
|
||||
{
|
||||
$this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator with an anonymous function.
|
||||
*
|
||||
* The anonymous function receives a \SplFileInfo and must return false
|
||||
* to remove files.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see CustomFilterIterator
|
||||
*/
|
||||
public function filter(\Closure $closure)
|
||||
{
|
||||
$this->filters[] = $closure;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the following of symlinks.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function followLinks()
|
||||
{
|
||||
$this->followLinks = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells finder to ignore unreadable directories.
|
||||
*
|
||||
* By default, scanning unreadable directories content throws an AccessDeniedException.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function ignoreUnreadableDirs(bool $ignore = true)
|
||||
{
|
||||
$this->ignoreUnreadableDirs = $ignore;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches files and directories which match defined rules.
|
||||
*
|
||||
* @param string|string[] $dirs A directory path or an array of directories
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws DirectoryNotFoundException if one of the directories does not exist
|
||||
*/
|
||||
public function in($dirs)
|
||||
{
|
||||
$resolvedDirs = [];
|
||||
|
||||
foreach ((array) $dirs as $dir) {
|
||||
if (is_dir($dir)) {
|
||||
$resolvedDirs[] = $this->normalizeDir($dir);
|
||||
} elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) {
|
||||
sort($glob);
|
||||
$resolvedDirs = array_merge($resolvedDirs, array_map([$this, 'normalizeDir'], $glob));
|
||||
} else {
|
||||
throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir));
|
||||
}
|
||||
}
|
||||
|
||||
$this->dirs = array_merge($this->dirs, $resolvedDirs);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for the current Finder configuration.
|
||||
*
|
||||
* This method implements the IteratorAggregate interface.
|
||||
*
|
||||
* @return \Iterator|SplFileInfo[] An iterator
|
||||
*
|
||||
* @throws \LogicException if the in() method has not been called
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
|
||||
throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
|
||||
}
|
||||
|
||||
if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
|
||||
return $this->searchInDirectory($this->dirs[0]);
|
||||
}
|
||||
|
||||
$iterator = new \AppendIterator();
|
||||
foreach ($this->dirs as $dir) {
|
||||
$iterator->append($this->searchInDirectory($dir));
|
||||
}
|
||||
|
||||
foreach ($this->iterators as $it) {
|
||||
$iterator->append($it);
|
||||
}
|
||||
|
||||
return $iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an existing set of files/directories to the finder.
|
||||
*
|
||||
* The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \InvalidArgumentException when the given argument is not iterable
|
||||
*/
|
||||
public function append(iterable $iterator)
|
||||
{
|
||||
if ($iterator instanceof \IteratorAggregate) {
|
||||
$this->iterators[] = $iterator->getIterator();
|
||||
} elseif ($iterator instanceof \Iterator) {
|
||||
$this->iterators[] = $iterator;
|
||||
} elseif ($iterator instanceof \Traversable || \is_array($iterator)) {
|
||||
$it = new \ArrayIterator();
|
||||
foreach ($iterator as $file) {
|
||||
$it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
|
||||
}
|
||||
$this->iterators[] = $it;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the any results were found.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasResults()
|
||||
{
|
||||
foreach ($this->getIterator() as $_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts all the results collected by the iterators.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return iterator_count($this->getIterator());
|
||||
}
|
||||
|
||||
private function searchInDirectory(string $dir): \Iterator
|
||||
{
|
||||
$exclude = $this->exclude;
|
||||
$notPaths = $this->notPaths;
|
||||
|
||||
if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
|
||||
$exclude = array_merge($exclude, self::$vcsPatterns);
|
||||
}
|
||||
|
||||
if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
|
||||
$notPaths[] = '#(^|/)\..+(/|$)#';
|
||||
}
|
||||
|
||||
if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
|
||||
$gitignoreFilePath = sprintf('%s/.gitignore', $dir);
|
||||
if (!is_readable($gitignoreFilePath)) {
|
||||
throw new \RuntimeException(sprintf('The "ignoreVCSIgnored" option cannot be used by the Finder as the "%s" file is not readable.', $gitignoreFilePath));
|
||||
}
|
||||
$notPaths = array_merge($notPaths, [Gitignore::toRegex(file_get_contents($gitignoreFilePath))]);
|
||||
}
|
||||
|
||||
$minDepth = 0;
|
||||
$maxDepth = PHP_INT_MAX;
|
||||
|
||||
foreach ($this->depths as $comparator) {
|
||||
switch ($comparator->getOperator()) {
|
||||
case '>':
|
||||
$minDepth = $comparator->getTarget() + 1;
|
||||
break;
|
||||
case '>=':
|
||||
$minDepth = $comparator->getTarget();
|
||||
break;
|
||||
case '<':
|
||||
$maxDepth = $comparator->getTarget() - 1;
|
||||
break;
|
||||
case '<=':
|
||||
$maxDepth = $comparator->getTarget();
|
||||
break;
|
||||
default:
|
||||
$minDepth = $maxDepth = $comparator->getTarget();
|
||||
}
|
||||
}
|
||||
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS;
|
||||
|
||||
if ($this->followLinks) {
|
||||
$flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
|
||||
}
|
||||
|
||||
$iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
|
||||
|
||||
if ($exclude) {
|
||||
$iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
|
||||
$iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
|
||||
}
|
||||
|
||||
if ($this->mode) {
|
||||
$iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
|
||||
}
|
||||
|
||||
if ($this->names || $this->notNames) {
|
||||
$iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
|
||||
}
|
||||
|
||||
if ($this->contains || $this->notContains) {
|
||||
$iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
|
||||
}
|
||||
|
||||
if ($this->sizes) {
|
||||
$iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
|
||||
}
|
||||
|
||||
if ($this->dates) {
|
||||
$iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
|
||||
}
|
||||
|
||||
if ($this->filters) {
|
||||
$iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
|
||||
}
|
||||
|
||||
if ($this->paths || $notPaths) {
|
||||
$iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
|
||||
}
|
||||
|
||||
if ($this->sort || $this->reverseSorting) {
|
||||
$iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting);
|
||||
$iterator = $iteratorAggregate->getIterator();
|
||||
}
|
||||
|
||||
return $iterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes given directory names by removing trailing slashes.
|
||||
*
|
||||
* Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper
|
||||
*/
|
||||
private function normalizeDir(string $dir): string
|
||||
{
|
||||
if ('/' === $dir) {
|
||||
return $dir;
|
||||
}
|
||||
|
||||
$dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
|
||||
|
||||
if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
|
||||
$dir .= '/';
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder;
|
||||
|
||||
/**
|
||||
* Gitignore matches against text.
|
||||
*
|
||||
* @author Ahmed Abdou <mail@ahmd.io>
|
||||
*/
|
||||
class Gitignore
|
||||
{
|
||||
/**
|
||||
* Returns a regexp which is the equivalent of the gitignore pattern.
|
||||
*
|
||||
* @return string The regexp
|
||||
*/
|
||||
public static function toRegex(string $gitignoreFileContent): string
|
||||
{
|
||||
$gitignoreFileContent = preg_replace('/^[^\\\r\n]*#.*/m', '', $gitignoreFileContent);
|
||||
$gitignoreLines = preg_split('/\r\n|\r|\n/', $gitignoreFileContent);
|
||||
$gitignoreLines = array_map('trim', $gitignoreLines);
|
||||
$gitignoreLines = array_filter($gitignoreLines);
|
||||
|
||||
$ignoreLinesPositive = array_filter($gitignoreLines, function (string $line) {
|
||||
return !preg_match('/^!/', $line);
|
||||
});
|
||||
|
||||
$ignoreLinesNegative = array_filter($gitignoreLines, function (string $line) {
|
||||
return preg_match('/^!/', $line);
|
||||
});
|
||||
|
||||
$ignoreLinesNegative = array_map(function (string $line) {
|
||||
return preg_replace('/^!(.*)/', '${1}', $line);
|
||||
}, $ignoreLinesNegative);
|
||||
$ignoreLinesNegative = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesNegative);
|
||||
|
||||
$ignoreLinesPositive = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesPositive);
|
||||
if (empty($ignoreLinesPositive)) {
|
||||
return '/^$/';
|
||||
}
|
||||
|
||||
if (empty($ignoreLinesNegative)) {
|
||||
return sprintf('/%s/', implode('|', $ignoreLinesPositive));
|
||||
}
|
||||
|
||||
return sprintf('/(?=^(?:(?!(%s)).)*$)(%s)/', implode('|', $ignoreLinesNegative), implode('|', $ignoreLinesPositive));
|
||||
}
|
||||
|
||||
private static function getRegexFromGitignore(string $gitignorePattern): string
|
||||
{
|
||||
$regex = '(';
|
||||
if (0 === strpos($gitignorePattern, '/')) {
|
||||
$gitignorePattern = substr($gitignorePattern, 1);
|
||||
$regex .= '^';
|
||||
} else {
|
||||
$regex .= '(^|\/)';
|
||||
}
|
||||
|
||||
if ('/' === $gitignorePattern[\strlen($gitignorePattern) - 1]) {
|
||||
$gitignorePattern = substr($gitignorePattern, 0, -1);
|
||||
}
|
||||
|
||||
$iMax = \strlen($gitignorePattern);
|
||||
for ($i = 0; $i < $iMax; ++$i) {
|
||||
$doubleChars = substr($gitignorePattern, $i, 2);
|
||||
if ('**' === $doubleChars) {
|
||||
$regex .= '.+';
|
||||
++$i;
|
||||
continue;
|
||||
}
|
||||
|
||||
$c = $gitignorePattern[$i];
|
||||
switch ($c) {
|
||||
case '*':
|
||||
$regex .= '[^\/]+';
|
||||
break;
|
||||
case '/':
|
||||
case '.':
|
||||
case ':':
|
||||
case '(':
|
||||
case ')':
|
||||
case '{':
|
||||
case '}':
|
||||
$regex .= '\\'.$c;
|
||||
break;
|
||||
default:
|
||||
$regex .= $c;
|
||||
}
|
||||
}
|
||||
|
||||
$regex .= '($|\/)';
|
||||
$regex .= ')';
|
||||
|
||||
return $regex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder;
|
||||
|
||||
/**
|
||||
* Glob matches globbing patterns against text.
|
||||
*
|
||||
* if match_glob("foo.*", "foo.bar") echo "matched\n";
|
||||
*
|
||||
* // prints foo.bar and foo.baz
|
||||
* $regex = glob_to_regex("foo.*");
|
||||
* for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t)
|
||||
* {
|
||||
* if (/$regex/) echo "matched: $car\n";
|
||||
* }
|
||||
*
|
||||
* Glob implements glob(3) style matching that can be used to match
|
||||
* against text, rather than fetching names from a filesystem.
|
||||
*
|
||||
* Based on the Perl Text::Glob module.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com> PHP port
|
||||
* @author Richard Clamp <richardc@unixbeard.net> Perl version
|
||||
* @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
|
||||
* @copyright 2002 Richard Clamp <richardc@unixbeard.net>
|
||||
*/
|
||||
class Glob
|
||||
{
|
||||
/**
|
||||
* Returns a regexp which is the equivalent of the glob pattern.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#')
|
||||
{
|
||||
$firstByte = true;
|
||||
$escaping = false;
|
||||
$inCurlies = 0;
|
||||
$regex = '';
|
||||
$sizeGlob = \strlen($glob);
|
||||
for ($i = 0; $i < $sizeGlob; ++$i) {
|
||||
$car = $glob[$i];
|
||||
if ($firstByte && $strictLeadingDot && '.' !== $car) {
|
||||
$regex .= '(?=[^\.])';
|
||||
}
|
||||
|
||||
$firstByte = '/' === $car;
|
||||
|
||||
if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
|
||||
$car = '[^/]++/';
|
||||
if (!isset($glob[$i + 3])) {
|
||||
$car .= '?';
|
||||
}
|
||||
|
||||
if ($strictLeadingDot) {
|
||||
$car = '(?=[^\.])'.$car;
|
||||
}
|
||||
|
||||
$car = '/(?:'.$car.')*';
|
||||
$i += 2 + isset($glob[$i + 3]);
|
||||
|
||||
if ('/' === $delimiter) {
|
||||
$car = str_replace('/', '\\/', $car);
|
||||
}
|
||||
}
|
||||
|
||||
if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
|
||||
$regex .= "\\$car";
|
||||
} elseif ('*' === $car) {
|
||||
$regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
|
||||
} elseif ('?' === $car) {
|
||||
$regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
|
||||
} elseif ('{' === $car) {
|
||||
$regex .= $escaping ? '\\{' : '(';
|
||||
if (!$escaping) {
|
||||
++$inCurlies;
|
||||
}
|
||||
} elseif ('}' === $car && $inCurlies) {
|
||||
$regex .= $escaping ? '}' : ')';
|
||||
if (!$escaping) {
|
||||
--$inCurlies;
|
||||
}
|
||||
} elseif (',' === $car && $inCurlies) {
|
||||
$regex .= $escaping ? ',' : '|';
|
||||
} elseif ('\\' === $car) {
|
||||
if ($escaping) {
|
||||
$regex .= '\\\\';
|
||||
$escaping = false;
|
||||
} else {
|
||||
$escaping = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else {
|
||||
$regex .= $car;
|
||||
}
|
||||
$escaping = false;
|
||||
}
|
||||
|
||||
return $delimiter.'^'.$regex.'$'.$delimiter;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* CustomFilterIterator filters files by applying anonymous functions.
|
||||
*
|
||||
* The anonymous function receives a \SplFileInfo and must return false
|
||||
* to remove files.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class CustomFilterIterator extends \FilterIterator
|
||||
{
|
||||
private $filters = [];
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param callable[] $filters An array of PHP callbacks
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, array $filters)
|
||||
{
|
||||
foreach ($filters as $filter) {
|
||||
if (!\is_callable($filter)) {
|
||||
throw new \InvalidArgumentException('Invalid PHP callback.');
|
||||
}
|
||||
}
|
||||
$this->filters = $filters;
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$fileinfo = $this->current();
|
||||
|
||||
foreach ($this->filters as $filter) {
|
||||
if (false === $filter($fileinfo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
use Symfony\Component\Finder\Comparator\DateComparator;
|
||||
|
||||
/**
|
||||
* DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DateRangeFilterIterator extends \FilterIterator
|
||||
{
|
||||
private $comparators = [];
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param DateComparator[] $comparators An array of DateComparator instances
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, array $comparators)
|
||||
{
|
||||
$this->comparators = $comparators;
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$fileinfo = $this->current();
|
||||
|
||||
if (!file_exists($fileinfo->getPathname())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filedate = $fileinfo->getMTime();
|
||||
foreach ($this->comparators as $compare) {
|
||||
if (!$compare->test($filedate)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* DepthRangeFilterIterator limits the directory depth.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class DepthRangeFilterIterator extends \FilterIterator
|
||||
{
|
||||
private $minDepth = 0;
|
||||
|
||||
/**
|
||||
* @param \RecursiveIteratorIterator $iterator The Iterator to filter
|
||||
* @param int $minDepth The min depth
|
||||
* @param int $maxDepth The max depth
|
||||
*/
|
||||
public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = PHP_INT_MAX)
|
||||
{
|
||||
$this->minDepth = $minDepth;
|
||||
$iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
return $this->getInnerIterator()->getDepth() >= $this->minDepth;
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* ExcludeDirectoryFilterIterator filters out directories.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator
|
||||
{
|
||||
private $iterator;
|
||||
private $isRecursive;
|
||||
private $excludedDirs = [];
|
||||
private $excludedPattern;
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param string[] $directories An array of directories to exclude
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, array $directories)
|
||||
{
|
||||
$this->iterator = $iterator;
|
||||
$this->isRecursive = $iterator instanceof \RecursiveIterator;
|
||||
$patterns = [];
|
||||
foreach ($directories as $directory) {
|
||||
$directory = rtrim($directory, '/');
|
||||
if (!$this->isRecursive || false !== strpos($directory, '/')) {
|
||||
$patterns[] = preg_quote($directory, '#');
|
||||
} else {
|
||||
$this->excludedDirs[$directory] = true;
|
||||
}
|
||||
}
|
||||
if ($patterns) {
|
||||
$this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
|
||||
}
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool True if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->excludedPattern) {
|
||||
$path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
|
||||
$path = str_replace('\\', '/', $path);
|
||||
|
||||
return !preg_match($this->excludedPattern, $path);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChildren()
|
||||
{
|
||||
return $this->isRecursive && $this->iterator->hasChildren();
|
||||
}
|
||||
|
||||
public function getChildren()
|
||||
{
|
||||
$children = new self($this->iterator->getChildren(), []);
|
||||
$children->excludedDirs = $this->excludedDirs;
|
||||
$children->excludedPattern = $this->excludedPattern;
|
||||
|
||||
return $children;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* FileTypeFilterIterator only keeps files, directories, or both.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class FileTypeFilterIterator extends \FilterIterator
|
||||
{
|
||||
const ONLY_FILES = 1;
|
||||
const ONLY_DIRECTORIES = 2;
|
||||
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, int $mode)
|
||||
{
|
||||
$this->mode = $mode;
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$fileinfo = $this->current();
|
||||
if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
|
||||
return false;
|
||||
} elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
|
||||
*/
|
||||
class FilecontentFilterIterator extends MultiplePcreFilterIterator
|
||||
{
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
if (!$this->matchRegexps && !$this->noMatchRegexps) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$fileinfo = $this->current();
|
||||
|
||||
if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = $fileinfo->getContents();
|
||||
if (!$content) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isAccepted($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string to regexp if necessary.
|
||||
*
|
||||
* @param string $str Pattern: string or regexp
|
||||
*
|
||||
* @return string regexp corresponding to a given string or regexp
|
||||
*/
|
||||
protected function toRegex(string $str)
|
||||
{
|
||||
return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
use Symfony\Component\Finder\Glob;
|
||||
|
||||
/**
|
||||
* FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class FilenameFilterIterator extends MultiplePcreFilterIterator
|
||||
{
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
return $this->isAccepted($this->current()->getFilename());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts glob to regexp.
|
||||
*
|
||||
* PCRE patterns are left unchanged.
|
||||
* Glob strings are transformed with Glob::toRegex().
|
||||
*
|
||||
* @param string $str Pattern: glob or regexp
|
||||
*
|
||||
* @return string regexp corresponding to a given glob or regexp
|
||||
*/
|
||||
protected function toRegex(string $str)
|
||||
{
|
||||
return $this->isRegex($str) ? $str : Glob::toRegex($str);
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class MultiplePcreFilterIterator extends \FilterIterator
|
||||
{
|
||||
protected $matchRegexps = [];
|
||||
protected $noMatchRegexps = [];
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param string[] $matchPatterns An array of patterns that need to match
|
||||
* @param string[] $noMatchPatterns An array of patterns that need to not match
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
|
||||
{
|
||||
foreach ($matchPatterns as $pattern) {
|
||||
$this->matchRegexps[] = $this->toRegex($pattern);
|
||||
}
|
||||
|
||||
foreach ($noMatchPatterns as $pattern) {
|
||||
$this->noMatchRegexps[] = $this->toRegex($pattern);
|
||||
}
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string is accepted by the regex filters.
|
||||
*
|
||||
* If there is no regexps defined in the class, this method will accept the string.
|
||||
* Such case can be handled by child classes before calling the method if they want to
|
||||
* apply a different behavior.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isAccepted(string $string)
|
||||
{
|
||||
// should at least not match one rule to exclude
|
||||
foreach ($this->noMatchRegexps as $regex) {
|
||||
if (preg_match($regex, $string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// should at least match one rule
|
||||
if ($this->matchRegexps) {
|
||||
foreach ($this->matchRegexps as $regex) {
|
||||
if (preg_match($regex, $string)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no match rules, the file is accepted
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the string is a regex.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isRegex(string $str)
|
||||
{
|
||||
if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
|
||||
$start = substr($m[1], 0, 1);
|
||||
$end = substr($m[1], -1);
|
||||
|
||||
if ($start === $end) {
|
||||
return !preg_match('/[*?[:alnum:] \\\\]/', $start);
|
||||
}
|
||||
|
||||
foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) {
|
||||
if ($start === $delimiters[0] && $end === $delimiters[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string into regexp.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function toRegex(string $str);
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* PathFilterIterator filters files by path patterns (e.g. some/special/dir).
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
|
||||
*/
|
||||
class PathFilterIterator extends MultiplePcreFilterIterator
|
||||
{
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$filename = $this->current()->getRelativePathname();
|
||||
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$filename = str_replace('\\', '/', $filename);
|
||||
}
|
||||
|
||||
return $this->isAccepted($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts strings to regexp.
|
||||
*
|
||||
* PCRE patterns are left unchanged.
|
||||
*
|
||||
* Default conversion:
|
||||
* 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/'
|
||||
*
|
||||
* Use only / as directory separator (on Windows also).
|
||||
*
|
||||
* @param string $str Pattern: regexp or dirname
|
||||
*
|
||||
* @return string regexp corresponding to a given string or regexp
|
||||
*/
|
||||
protected function toRegex(string $str)
|
||||
{
|
||||
return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
use Symfony\Component\Finder\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
/**
|
||||
* Extends the \RecursiveDirectoryIterator to support relative paths.
|
||||
*
|
||||
* @author Victor Berchet <victor@suumit.com>
|
||||
*/
|
||||
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $ignoreUnreadableDirs;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $rewindable;
|
||||
|
||||
// these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
|
||||
private $rootPath;
|
||||
private $subPath;
|
||||
private $directorySeparator = '/';
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false)
|
||||
{
|
||||
if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
|
||||
throw new \RuntimeException('This iterator only support returning current as fileinfo.');
|
||||
}
|
||||
|
||||
parent::__construct($path, $flags);
|
||||
$this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
|
||||
$this->rootPath = $path;
|
||||
if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
|
||||
$this->directorySeparator = \DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of SplFileInfo with support for relative paths.
|
||||
*
|
||||
* @return SplFileInfo File information
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
// the logic here avoids redoing the same work in all iterations
|
||||
|
||||
if (null === $subPathname = $this->subPath) {
|
||||
$subPathname = $this->subPath = (string) $this->getSubPath();
|
||||
}
|
||||
if ('' !== $subPathname) {
|
||||
$subPathname .= $this->directorySeparator;
|
||||
}
|
||||
$subPathname .= $this->getFilename();
|
||||
|
||||
if ('/' !== $basePath = $this->rootPath) {
|
||||
$basePath .= $this->directorySeparator;
|
||||
}
|
||||
|
||||
return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RecursiveIterator
|
||||
*
|
||||
* @throws AccessDeniedException
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
try {
|
||||
$children = parent::getChildren();
|
||||
|
||||
if ($children instanceof self) {
|
||||
// parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
|
||||
$children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
|
||||
|
||||
// performance optimization to avoid redoing the same work in all children
|
||||
$children->rewindable = &$this->rewindable;
|
||||
$children->rootPath = $this->rootPath;
|
||||
}
|
||||
|
||||
return $children;
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
if ($this->ignoreUnreadableDirs) {
|
||||
// If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
|
||||
return new \RecursiveArrayIterator([]);
|
||||
} else {
|
||||
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing for non rewindable stream.
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
if (false === $this->isRewindable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::rewind();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the stream is rewindable.
|
||||
*
|
||||
* @return bool true when the stream is rewindable, false otherwise
|
||||
*/
|
||||
public function isRewindable()
|
||||
{
|
||||
if (null !== $this->rewindable) {
|
||||
return $this->rewindable;
|
||||
}
|
||||
|
||||
if (false !== $stream = @opendir($this->getPath())) {
|
||||
$infos = stream_get_meta_data($stream);
|
||||
closedir($stream);
|
||||
|
||||
if ($infos['seekable']) {
|
||||
return $this->rewindable = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->rewindable = false;
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
use Symfony\Component\Finder\Comparator\NumberComparator;
|
||||
|
||||
/**
|
||||
* SizeRangeFilterIterator filters out files that are not in the given size range.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class SizeRangeFilterIterator extends \FilterIterator
|
||||
{
|
||||
private $comparators = [];
|
||||
|
||||
/**
|
||||
* @param \Iterator $iterator The Iterator to filter
|
||||
* @param NumberComparator[] $comparators An array of NumberComparator instances
|
||||
*/
|
||||
public function __construct(\Iterator $iterator, array $comparators)
|
||||
{
|
||||
$this->comparators = $comparators;
|
||||
|
||||
parent::__construct($iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the iterator values.
|
||||
*
|
||||
* @return bool true if the value should be kept, false otherwise
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
$fileinfo = $this->current();
|
||||
if (!$fileinfo->isFile()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$filesize = $fileinfo->getSize();
|
||||
foreach ($this->comparators as $compare) {
|
||||
if (!$compare->test($filesize)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder\Iterator;
|
||||
|
||||
/**
|
||||
* SortableIterator applies a sort on a given Iterator.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class SortableIterator implements \IteratorAggregate
|
||||
{
|
||||
const SORT_BY_NONE = 0;
|
||||
const SORT_BY_NAME = 1;
|
||||
const SORT_BY_TYPE = 2;
|
||||
const SORT_BY_ACCESSED_TIME = 3;
|
||||
const SORT_BY_CHANGED_TIME = 4;
|
||||
const SORT_BY_MODIFIED_TIME = 5;
|
||||
const SORT_BY_NAME_NATURAL = 6;
|
||||
|
||||
private $iterator;
|
||||
private $sort;
|
||||
|
||||
/**
|
||||
* @param \Traversable $iterator The Iterator to filter
|
||||
* @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false)
|
||||
{
|
||||
$this->iterator = $iterator;
|
||||
$order = $reverseOrder ? -1 : 1;
|
||||
|
||||
if (self::SORT_BY_NAME === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
|
||||
};
|
||||
} elseif (self::SORT_BY_NAME_NATURAL === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
|
||||
};
|
||||
} elseif (self::SORT_BY_TYPE === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
if ($a->isDir() && $b->isFile()) {
|
||||
return -$order;
|
||||
} elseif ($a->isFile() && $b->isDir()) {
|
||||
return $order;
|
||||
}
|
||||
|
||||
return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
|
||||
};
|
||||
} elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
return $order * ($a->getATime() - $b->getATime());
|
||||
};
|
||||
} elseif (self::SORT_BY_CHANGED_TIME === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
return $order * ($a->getCTime() - $b->getCTime());
|
||||
};
|
||||
} elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
|
||||
$this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
|
||||
return $order * ($a->getMTime() - $b->getMTime());
|
||||
};
|
||||
} elseif (self::SORT_BY_NONE === $sort) {
|
||||
$this->sort = $order;
|
||||
} elseif (\is_callable($sort)) {
|
||||
$this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
if (1 === $this->sort) {
|
||||
return $this->iterator;
|
||||
}
|
||||
|
||||
$array = iterator_to_array($this->iterator, true);
|
||||
|
||||
if (-1 === $this->sort) {
|
||||
$array = array_reverse($array);
|
||||
} else {
|
||||
uasort($array, $this->sort);
|
||||
}
|
||||
|
||||
return new \ArrayIterator($array);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2020 Fabien Potencier
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,14 @@
|
||||
Finder Component
|
||||
================
|
||||
|
||||
The Finder component finds files and directories via an intuitive fluent
|
||||
interface.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/finder.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Finder;
|
||||
|
||||
/**
|
||||
* Extends \SplFileInfo to support relative paths.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class SplFileInfo extends \SplFileInfo
|
||||
{
|
||||
private $relativePath;
|
||||
private $relativePathname;
|
||||
|
||||
/**
|
||||
* @param string $file The file name
|
||||
* @param string $relativePath The relative path
|
||||
* @param string $relativePathname The relative path name
|
||||
*/
|
||||
public function __construct(string $file, string $relativePath, string $relativePathname)
|
||||
{
|
||||
parent::__construct($file);
|
||||
$this->relativePath = $relativePath;
|
||||
$this->relativePathname = $relativePathname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative path.
|
||||
*
|
||||
* This path does not contain the file name.
|
||||
*
|
||||
* @return string the relative path
|
||||
*/
|
||||
public function getRelativePath()
|
||||
{
|
||||
return $this->relativePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative path name.
|
||||
*
|
||||
* This path contains the file name.
|
||||
*
|
||||
* @return string the relative path name
|
||||
*/
|
||||
public function getRelativePathname()
|
||||
{
|
||||
return $this->relativePathname;
|
||||
}
|
||||
|
||||
public function getFilenameWithoutExtension(): string
|
||||
{
|
||||
$filename = $this->getFilename();
|
||||
|
||||
return pathinfo($filename, PATHINFO_FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the file.
|
||||
*
|
||||
* @return string the contents of the file
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getContents()
|
||||
{
|
||||
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
|
||||
$content = file_get_contents($this->getPathname());
|
||||
restore_error_handler();
|
||||
if (false === $content) {
|
||||
throw new \RuntimeException($error);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"type": "library",
|
||||
"description": "Symfony Finder Component",
|
||||
"keywords": [],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Finder\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.1-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Iconv;
|
||||
|
||||
/**
|
||||
* iconv implementation in pure PHP, UTF-8 centric.
|
||||
*
|
||||
* Implemented:
|
||||
* - iconv - Convert string to requested character encoding
|
||||
* - iconv_mime_decode - Decodes a MIME header field
|
||||
* - iconv_mime_decode_headers - Decodes multiple MIME header fields at once
|
||||
* - iconv_get_encoding - Retrieve internal configuration variables of iconv extension
|
||||
* - iconv_set_encoding - Set current setting for character encoding conversion
|
||||
* - iconv_mime_encode - Composes a MIME header field
|
||||
* - iconv_strlen - Returns the character count of string
|
||||
* - iconv_strpos - Finds position of first occurrence of a needle within a haystack
|
||||
* - iconv_strrpos - Finds the last occurrence of a needle within a haystack
|
||||
* - iconv_substr - Cut out part of a string
|
||||
*
|
||||
* Charsets available for conversion are defined by files
|
||||
* in the charset/ directory and by Iconv::$alias below.
|
||||
* You're welcome to send back any addition you make.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Iconv
|
||||
{
|
||||
const ERROR_ILLEGAL_CHARACTER = 'iconv(): Detected an illegal character in input string';
|
||||
const ERROR_WRONG_CHARSET = 'iconv(): Wrong charset, conversion from `%s\' to `%s\' is not allowed';
|
||||
|
||||
public static $inputEncoding = 'utf-8';
|
||||
public static $outputEncoding = 'utf-8';
|
||||
public static $internalEncoding = 'utf-8';
|
||||
|
||||
private static $alias = array(
|
||||
'utf8' => 'utf-8',
|
||||
'ascii' => 'us-ascii',
|
||||
'tis-620' => 'iso-8859-11',
|
||||
'cp1250' => 'windows-1250',
|
||||
'cp1251' => 'windows-1251',
|
||||
'cp1252' => 'windows-1252',
|
||||
'cp1253' => 'windows-1253',
|
||||
'cp1254' => 'windows-1254',
|
||||
'cp1255' => 'windows-1255',
|
||||
'cp1256' => 'windows-1256',
|
||||
'cp1257' => 'windows-1257',
|
||||
'cp1258' => 'windows-1258',
|
||||
'shift-jis' => 'cp932',
|
||||
'shift_jis' => 'cp932',
|
||||
'latin1' => 'iso-8859-1',
|
||||
'latin2' => 'iso-8859-2',
|
||||
'latin3' => 'iso-8859-3',
|
||||
'latin4' => 'iso-8859-4',
|
||||
'latin5' => 'iso-8859-9',
|
||||
'latin6' => 'iso-8859-10',
|
||||
'latin7' => 'iso-8859-13',
|
||||
'latin8' => 'iso-8859-14',
|
||||
'latin9' => 'iso-8859-15',
|
||||
'latin10' => 'iso-8859-16',
|
||||
'iso8859-1' => 'iso-8859-1',
|
||||
'iso8859-2' => 'iso-8859-2',
|
||||
'iso8859-3' => 'iso-8859-3',
|
||||
'iso8859-4' => 'iso-8859-4',
|
||||
'iso8859-5' => 'iso-8859-5',
|
||||
'iso8859-6' => 'iso-8859-6',
|
||||
'iso8859-7' => 'iso-8859-7',
|
||||
'iso8859-8' => 'iso-8859-8',
|
||||
'iso8859-9' => 'iso-8859-9',
|
||||
'iso8859-10' => 'iso-8859-10',
|
||||
'iso8859-11' => 'iso-8859-11',
|
||||
'iso8859-12' => 'iso-8859-12',
|
||||
'iso8859-13' => 'iso-8859-13',
|
||||
'iso8859-14' => 'iso-8859-14',
|
||||
'iso8859-15' => 'iso-8859-15',
|
||||
'iso8859-16' => 'iso-8859-16',
|
||||
'iso_8859-1' => 'iso-8859-1',
|
||||
'iso_8859-2' => 'iso-8859-2',
|
||||
'iso_8859-3' => 'iso-8859-3',
|
||||
'iso_8859-4' => 'iso-8859-4',
|
||||
'iso_8859-5' => 'iso-8859-5',
|
||||
'iso_8859-6' => 'iso-8859-6',
|
||||
'iso_8859-7' => 'iso-8859-7',
|
||||
'iso_8859-8' => 'iso-8859-8',
|
||||
'iso_8859-9' => 'iso-8859-9',
|
||||
'iso_8859-10' => 'iso-8859-10',
|
||||
'iso_8859-11' => 'iso-8859-11',
|
||||
'iso_8859-12' => 'iso-8859-12',
|
||||
'iso_8859-13' => 'iso-8859-13',
|
||||
'iso_8859-14' => 'iso-8859-14',
|
||||
'iso_8859-15' => 'iso-8859-15',
|
||||
'iso_8859-16' => 'iso-8859-16',
|
||||
'iso88591' => 'iso-8859-1',
|
||||
'iso88592' => 'iso-8859-2',
|
||||
'iso88593' => 'iso-8859-3',
|
||||
'iso88594' => 'iso-8859-4',
|
||||
'iso88595' => 'iso-8859-5',
|
||||
'iso88596' => 'iso-8859-6',
|
||||
'iso88597' => 'iso-8859-7',
|
||||
'iso88598' => 'iso-8859-8',
|
||||
'iso88599' => 'iso-8859-9',
|
||||
'iso885910' => 'iso-8859-10',
|
||||
'iso885911' => 'iso-8859-11',
|
||||
'iso885912' => 'iso-8859-12',
|
||||
'iso885913' => 'iso-8859-13',
|
||||
'iso885914' => 'iso-8859-14',
|
||||
'iso885915' => 'iso-8859-15',
|
||||
'iso885916' => 'iso-8859-16',
|
||||
);
|
||||
private static $translitMap = array();
|
||||
private static $convertMap = array();
|
||||
private static $errorHandler;
|
||||
private static $lastError;
|
||||
|
||||
private static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
|
||||
private static $isValidUtf8;
|
||||
|
||||
public static function iconv($inCharset, $outCharset, $str)
|
||||
{
|
||||
$str = (string) $str;
|
||||
if ('' === $str) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Prepare for //IGNORE and //TRANSLIT
|
||||
|
||||
$translit = $ignore = '';
|
||||
|
||||
$outCharset = strtolower($outCharset);
|
||||
$inCharset = strtolower($inCharset);
|
||||
|
||||
if ('' === $outCharset) {
|
||||
$outCharset = 'iso-8859-1';
|
||||
}
|
||||
if ('' === $inCharset) {
|
||||
$inCharset = 'iso-8859-1';
|
||||
}
|
||||
|
||||
do {
|
||||
$loop = false;
|
||||
|
||||
if ('//translit' === substr($outCharset, -10)) {
|
||||
$loop = $translit = true;
|
||||
$outCharset = substr($outCharset, 0, -10);
|
||||
}
|
||||
|
||||
if ('//ignore' === substr($outCharset, -8)) {
|
||||
$loop = $ignore = true;
|
||||
$outCharset = substr($outCharset, 0, -8);
|
||||
}
|
||||
} while ($loop);
|
||||
|
||||
do {
|
||||
$loop = false;
|
||||
|
||||
if ('//translit' === substr($inCharset, -10)) {
|
||||
$loop = true;
|
||||
$inCharset = substr($inCharset, 0, -10);
|
||||
}
|
||||
|
||||
if ('//ignore' === substr($inCharset, -8)) {
|
||||
$loop = true;
|
||||
$inCharset = substr($inCharset, 0, -8);
|
||||
}
|
||||
} while ($loop);
|
||||
|
||||
if (isset(self::$alias[$inCharset])) {
|
||||
$inCharset = self::$alias[$inCharset];
|
||||
}
|
||||
if (isset(self::$alias[$outCharset])) {
|
||||
$outCharset = self::$alias[$outCharset];
|
||||
}
|
||||
|
||||
// Load charset maps
|
||||
|
||||
if (('utf-8' !== $inCharset && !self::loadMap('from.', $inCharset, $inMap))
|
||||
|| ('utf-8' !== $outCharset && !self::loadMap('to.', $outCharset, $outMap))) {
|
||||
trigger_error(sprintf(self::ERROR_WRONG_CHARSET, $inCharset, $outCharset));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('utf-8' !== $inCharset) {
|
||||
// Convert input to UTF-8
|
||||
$result = '';
|
||||
if (self::mapToUtf8($result, $inMap, $str, $ignore)) {
|
||||
$str = $result;
|
||||
} else {
|
||||
$str = false;
|
||||
}
|
||||
self::$isValidUtf8 = true;
|
||||
} else {
|
||||
self::$isValidUtf8 = preg_match('//u', $str);
|
||||
|
||||
if (!self::$isValidUtf8 && !$ignore) {
|
||||
trigger_error(self::ERROR_ILLEGAL_CHARACTER);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('utf-8' === $outCharset) {
|
||||
// UTF-8 validation
|
||||
$str = self::utf8ToUtf8($str, $ignore);
|
||||
}
|
||||
}
|
||||
|
||||
if ('utf-8' !== $outCharset && false !== $str) {
|
||||
// Convert output to UTF-8
|
||||
$result = '';
|
||||
if (self::mapFromUtf8($result, $outMap, $str, $ignore, $translit)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
public static function iconv_mime_decode_headers($str, $mode = 0, $charset = null)
|
||||
{
|
||||
if (null === $charset) {
|
||||
$charset = self::$internalEncoding;
|
||||
}
|
||||
|
||||
if (false !== strpos($str, "\r")) {
|
||||
$str = strtr(str_replace("\r\n", "\n", $str), "\r", "\n");
|
||||
}
|
||||
$str = explode("\n\n", $str, 2);
|
||||
|
||||
$headers = array();
|
||||
|
||||
$str = preg_split('/\n(?![ \t])/', $str[0]);
|
||||
foreach ($str as $str) {
|
||||
$str = self::iconv_mime_decode($str, $mode, $charset);
|
||||
if (false === $str) {
|
||||
return false;
|
||||
}
|
||||
$str = explode(':', $str, 2);
|
||||
|
||||
if (2 === \count($str)) {
|
||||
if (isset($headers[$str[0]])) {
|
||||
if (!\is_array($headers[$str[0]])) {
|
||||
$headers[$str[0]] = array($headers[$str[0]]);
|
||||
}
|
||||
$headers[$str[0]][] = ltrim($str[1]);
|
||||
} else {
|
||||
$headers[$str[0]] = ltrim($str[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
public static function iconv_mime_decode($str, $mode = 0, $charset = null)
|
||||
{
|
||||
if (null === $charset) {
|
||||
$charset = self::$internalEncoding;
|
||||
}
|
||||
if (ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode) {
|
||||
$charset .= '//IGNORE';
|
||||
}
|
||||
|
||||
if (false !== strpos($str, "\r")) {
|
||||
$str = strtr(str_replace("\r\n", "\n", $str), "\r", "\n");
|
||||
}
|
||||
$str = preg_split('/\n(?![ \t])/', rtrim($str), 2);
|
||||
$str = preg_replace('/[ \t]*\n[ \t]+/', ' ', rtrim($str[0]));
|
||||
$str = preg_split('/=\?([^?]+)\?([bqBQ])\?(.*?)\?=/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
$result = self::iconv('utf-8', $charset, $str[0]);
|
||||
if (false === $result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
$len = \count($str);
|
||||
|
||||
while ($i < $len) {
|
||||
$c = strtolower($str[$i]);
|
||||
if ((ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode)
|
||||
&& 'utf-8' !== $c
|
||||
&& !isset(self::$alias[$c])
|
||||
&& !self::loadMap('from.', $c, $d)) {
|
||||
$d = false;
|
||||
} elseif ('B' === strtoupper($str[$i + 1])) {
|
||||
$d = base64_decode($str[$i + 2]);
|
||||
} else {
|
||||
$d = rawurldecode(strtr(str_replace('%', '%25', $str[$i + 2]), '=_', '% '));
|
||||
}
|
||||
|
||||
if (false !== $d) {
|
||||
if ('' !== $d) {
|
||||
if ('' === $d = self::iconv($c, $charset, $d)) {
|
||||
$str[$i + 3] = substr($str[$i + 3], 1);
|
||||
} else {
|
||||
$result .= $d;
|
||||
}
|
||||
}
|
||||
$d = self::iconv('utf-8', $charset, $str[$i + 3]);
|
||||
if ('' !== trim($d)) {
|
||||
$result .= $d;
|
||||
}
|
||||
} elseif (ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode) {
|
||||
$result .= "=?{$str[$i]}?{$str[$i + 1]}?{$str[$i + 2]}?={$str[$i + 3]}";
|
||||
} else {
|
||||
$result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
$i += 4;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function iconv_get_encoding($type = 'all')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'input_encoding': return self::$inputEncoding;
|
||||
case 'output_encoding': return self::$outputEncoding;
|
||||
case 'internal_encoding': return self::$internalEncoding;
|
||||
}
|
||||
|
||||
return array(
|
||||
'input_encoding' => self::$inputEncoding,
|
||||
'output_encoding' => self::$outputEncoding,
|
||||
'internal_encoding' => self::$internalEncoding,
|
||||
);
|
||||
}
|
||||
|
||||
public static function iconv_set_encoding($type, $charset)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'input_encoding': self::$inputEncoding = $charset; break;
|
||||
case 'output_encoding': self::$outputEncoding = $charset; break;
|
||||
case 'internal_encoding': self::$internalEncoding = $charset; break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function iconv_mime_encode($fieldName, $fieldValue, $pref = null)
|
||||
{
|
||||
if (!\is_array($pref)) {
|
||||
$pref = array();
|
||||
}
|
||||
|
||||
$pref += array(
|
||||
'scheme' => 'B',
|
||||
'input-charset' => self::$internalEncoding,
|
||||
'output-charset' => self::$internalEncoding,
|
||||
'line-length' => 76,
|
||||
'line-break-chars' => "\r\n",
|
||||
);
|
||||
|
||||
if (preg_match('/[\x80-\xFF]/', $fieldName)) {
|
||||
$fieldName = '';
|
||||
}
|
||||
|
||||
$scheme = strtoupper(substr($pref['scheme'], 0, 1));
|
||||
$in = strtolower($pref['input-charset']);
|
||||
$out = strtolower($pref['output-charset']);
|
||||
|
||||
if ('utf-8' !== $in && false === $fieldValue = self::iconv($in, 'utf-8', $fieldValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
preg_match_all('/./us', $fieldValue, $chars);
|
||||
|
||||
$chars = isset($chars[0]) ? $chars[0] : array();
|
||||
|
||||
$lineBreak = (int) $pref['line-length'];
|
||||
$lineStart = "=?{$pref['output-charset']}?{$scheme}?";
|
||||
$lineLength = \strlen($fieldName) + 2 + \strlen($lineStart) + 2;
|
||||
$lineOffset = \strlen($lineStart) + 3;
|
||||
$lineData = '';
|
||||
|
||||
$fieldValue = array();
|
||||
|
||||
$Q = 'Q' === $scheme;
|
||||
|
||||
foreach ($chars as $c) {
|
||||
if ('utf-8' !== $out && false === $c = self::iconv('utf-8', $out, $c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$o = $Q
|
||||
? $c = preg_replace_callback(
|
||||
'/[=_\?\x00-\x1F\x80-\xFF]/',
|
||||
array(__CLASS__, 'qpByteCallback'),
|
||||
$c
|
||||
)
|
||||
: base64_encode($lineData.$c);
|
||||
|
||||
if (isset($o[$lineBreak - $lineLength])) {
|
||||
if (!$Q) {
|
||||
$lineData = base64_encode($lineData);
|
||||
}
|
||||
$fieldValue[] = $lineStart.$lineData.'?=';
|
||||
$lineLength = $lineOffset;
|
||||
$lineData = '';
|
||||
}
|
||||
|
||||
$lineData .= $c;
|
||||
$Q && $lineLength += \strlen($c);
|
||||
}
|
||||
|
||||
if ('' !== $lineData) {
|
||||
if (!$Q) {
|
||||
$lineData = base64_encode($lineData);
|
||||
}
|
||||
$fieldValue[] = $lineStart.$lineData.'?=';
|
||||
}
|
||||
|
||||
return $fieldName.': '.implode($pref['line-break-chars'].' ', $fieldValue);
|
||||
}
|
||||
|
||||
public static function iconv_strlen($s, $encoding = null)
|
||||
{
|
||||
static $hasXml = null;
|
||||
if (null === $hasXml) {
|
||||
$hasXml = \extension_loaded('xml');
|
||||
}
|
||||
|
||||
if ($hasXml) {
|
||||
return self::strlen1($s, $encoding);
|
||||
}
|
||||
|
||||
return self::strlen2($s, $encoding);
|
||||
}
|
||||
|
||||
public static function strlen1($s, $encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
if (0 !== stripos($encoding, 'utf-8') && false === $s = self::iconv($encoding, 'utf-8', $s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return \strlen(utf8_decode($s));
|
||||
}
|
||||
|
||||
public static function strlen2($s, $encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
if (0 !== stripos($encoding, 'utf-8') && false === $s = self::iconv($encoding, 'utf-8', $s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ulenMask = self::$ulenMask;
|
||||
|
||||
$i = 0;
|
||||
$j = 0;
|
||||
$len = \strlen($s);
|
||||
|
||||
while ($i < $len) {
|
||||
$u = $s[$i] & "\xF0";
|
||||
$i += isset($ulenMask[$u]) ? $ulenMask[$u] : 1;
|
||||
++$j;
|
||||
}
|
||||
|
||||
return $j;
|
||||
}
|
||||
|
||||
public static function iconv_strpos($haystack, $needle, $offset = 0, $encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
|
||||
if (0 !== stripos($encoding, 'utf-8')) {
|
||||
if (false === $haystack = self::iconv($encoding, 'utf-8', $haystack)) {
|
||||
return false;
|
||||
}
|
||||
if (false === $needle = self::iconv($encoding, 'utf-8', $needle)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($offset = (int) $offset) {
|
||||
$haystack = self::iconv_substr($haystack, $offset, 2147483647, 'utf-8');
|
||||
}
|
||||
$pos = strpos($haystack, $needle);
|
||||
|
||||
return false === $pos ? false : ($offset + ($pos ? self::iconv_strlen(substr($haystack, 0, $pos), 'utf-8') : 0));
|
||||
}
|
||||
|
||||
public static function iconv_strrpos($haystack, $needle, $encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
|
||||
if (0 !== stripos($encoding, 'utf-8')) {
|
||||
if (false === $haystack = self::iconv($encoding, 'utf-8', $haystack)) {
|
||||
return false;
|
||||
}
|
||||
if (false === $needle = self::iconv($encoding, 'utf-8', $needle)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$pos = isset($needle[0]) ? strrpos($haystack, $needle) : false;
|
||||
|
||||
return false === $pos ? false : self::iconv_strlen($pos ? substr($haystack, 0, $pos) : $haystack, 'utf-8');
|
||||
}
|
||||
|
||||
public static function iconv_substr($s, $start, $length = 2147483647, $encoding = null)
|
||||
{
|
||||
if (null === $encoding) {
|
||||
$encoding = self::$internalEncoding;
|
||||
}
|
||||
if (0 !== stripos($encoding, 'utf-8')) {
|
||||
$encoding = null;
|
||||
} elseif (false === $s = self::iconv($encoding, 'utf-8', $s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$s = (string) $s;
|
||||
$slen = self::iconv_strlen($s, 'utf-8');
|
||||
$start = (int) $start;
|
||||
|
||||
if (0 > $start) {
|
||||
$start += $slen;
|
||||
}
|
||||
if (0 > $start) {
|
||||
return false;
|
||||
}
|
||||
if ($start >= $slen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$rx = $slen - $start;
|
||||
|
||||
if (0 > $length) {
|
||||
$length += $rx;
|
||||
}
|
||||
if (0 === $length) {
|
||||
return '';
|
||||
}
|
||||
if (0 > $length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($length > $rx) {
|
||||
$length = $rx;
|
||||
}
|
||||
|
||||
$rx = '/^'.($start ? self::pregOffset($start) : '').'('.self::pregOffset($length).')/u';
|
||||
|
||||
$s = preg_match($rx, $s, $s) ? $s[1] : '';
|
||||
|
||||
if (null === $encoding) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return self::iconv('utf-8', $encoding, $s);
|
||||
}
|
||||
|
||||
private static function loadMap($type, $charset, &$map)
|
||||
{
|
||||
if (!isset(self::$convertMap[$type.$charset])) {
|
||||
if (false === $map = self::getData($type.$charset)) {
|
||||
if ('to.' === $type && self::loadMap('from.', $charset, $map)) {
|
||||
$map = array_flip($map);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self::$convertMap[$type.$charset] = $map;
|
||||
} else {
|
||||
$map = self::$convertMap[$type.$charset];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function utf8ToUtf8($str, $ignore)
|
||||
{
|
||||
$ulenMask = self::$ulenMask;
|
||||
$valid = self::$isValidUtf8;
|
||||
|
||||
$u = $str;
|
||||
$i = $j = 0;
|
||||
$len = \strlen($str);
|
||||
|
||||
while ($i < $len) {
|
||||
if ($str[$i] < "\x80") {
|
||||
$u[$j++] = $str[$i++];
|
||||
} else {
|
||||
$ulen = $str[$i] & "\xF0";
|
||||
$ulen = isset($ulenMask[$ulen]) ? $ulenMask[$ulen] : 1;
|
||||
$uchr = substr($str, $i, $ulen);
|
||||
|
||||
if (1 === $ulen || !($valid || preg_match('/^.$/us', $uchr))) {
|
||||
if ($ignore) {
|
||||
++$i;
|
||||
continue;
|
||||
}
|
||||
|
||||
trigger_error(self::ERROR_ILLEGAL_CHARACTER);
|
||||
|
||||
return false;
|
||||
} else {
|
||||
$i += $ulen;
|
||||
}
|
||||
|
||||
$u[$j++] = $uchr[0];
|
||||
|
||||
isset($uchr[1]) && 0 !== ($u[$j++] = $uchr[1])
|
||||
&& isset($uchr[2]) && 0 !== ($u[$j++] = $uchr[2])
|
||||
&& isset($uchr[3]) && 0 !== ($u[$j++] = $uchr[3]);
|
||||
}
|
||||
}
|
||||
|
||||
return substr($u, 0, $j);
|
||||
}
|
||||
|
||||
private static function mapToUtf8(&$result, array $map, $str, $ignore)
|
||||
{
|
||||
$len = \strlen($str);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
if (isset($str[$i + 1], $map[$str[$i].$str[$i + 1]])) {
|
||||
$result .= $map[$str[$i].$str[++$i]];
|
||||
} elseif (isset($map[$str[$i]])) {
|
||||
$result .= $map[$str[$i]];
|
||||
} elseif (!$ignore) {
|
||||
trigger_error(self::ERROR_ILLEGAL_CHARACTER);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function mapFromUtf8(&$result, array $map, $str, $ignore, $translit)
|
||||
{
|
||||
$ulenMask = self::$ulenMask;
|
||||
$valid = self::$isValidUtf8;
|
||||
|
||||
if ($translit && !self::$translitMap) {
|
||||
self::$translitMap = self::getData('translit');
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$len = \strlen($str);
|
||||
|
||||
while ($i < $len) {
|
||||
if ($str[$i] < "\x80") {
|
||||
$uchr = $str[$i++];
|
||||
} else {
|
||||
$ulen = $str[$i] & "\xF0";
|
||||
$ulen = isset($ulenMask[$ulen]) ? $ulenMask[$ulen] : 1;
|
||||
$uchr = substr($str, $i, $ulen);
|
||||
|
||||
if ($ignore && (1 === $ulen || !($valid || preg_match('/^.$/us', $uchr)))) {
|
||||
++$i;
|
||||
continue;
|
||||
} else {
|
||||
$i += $ulen;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($map[$uchr])) {
|
||||
$result .= $map[$uchr];
|
||||
} elseif ($translit) {
|
||||
if (isset(self::$translitMap[$uchr])) {
|
||||
$uchr = self::$translitMap[$uchr];
|
||||
} elseif ($uchr >= "\xC3\x80") {
|
||||
$uchr = \Normalizer::normalize($uchr, \Normalizer::NFD);
|
||||
|
||||
if ($uchr[0] < "\x80") {
|
||||
$uchr = $uchr[0];
|
||||
} elseif ($ignore) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} elseif ($ignore) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$str = $uchr.substr($str, $i);
|
||||
$len = \strlen($str);
|
||||
$i = 0;
|
||||
} elseif (!$ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function qpByteCallback(array $m)
|
||||
{
|
||||
return '='.strtoupper(dechex(\ord($m[0])));
|
||||
}
|
||||
|
||||
private static function pregOffset($offset)
|
||||
{
|
||||
$rx = array();
|
||||
$offset = (int) $offset;
|
||||
|
||||
while ($offset > 65535) {
|
||||
$rx[] = '.{65535}';
|
||||
$offset -= 65535;
|
||||
}
|
||||
|
||||
return implode('', $rx).'.{'.$offset.'}';
|
||||
}
|
||||
|
||||
private static function getData($file)
|
||||
{
|
||||
if (file_exists($file = __DIR__.'/Resources/charset/'.$file.'.php')) {
|
||||
return require $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-2019 Fabien Potencier
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,14 @@
|
||||
Symfony Polyfill / Iconv
|
||||
========================
|
||||
|
||||
This component provides a native PHP implementation of the
|
||||
[php.net/iconv](https://php.net/iconv) functions
|
||||
(short of [`ob_iconv_handler`](https://php.net/ob-iconv-handler)).
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
+13719
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
+4103
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Iconv as p;
|
||||
|
||||
if (extension_loaded('iconv')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('ICONV_IMPL')) {
|
||||
define('ICONV_IMPL', 'Symfony');
|
||||
}
|
||||
if (!defined('ICONV_VERSION')) {
|
||||
define('ICONV_VERSION', '1.0');
|
||||
}
|
||||
if (!defined('ICONV_MIME_DECODE_STRICT')) {
|
||||
define('ICONV_MIME_DECODE_STRICT', 1);
|
||||
}
|
||||
if (!defined('ICONV_MIME_DECODE_CONTINUE_ON_ERROR')) {
|
||||
define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2);
|
||||
}
|
||||
|
||||
if (!function_exists('iconv')) {
|
||||
function iconv($from, $to, $s) { return p\Iconv::iconv($from, $to, $s); }
|
||||
}
|
||||
if (!function_exists('iconv_get_encoding')) {
|
||||
function iconv_get_encoding($type = 'all') { return p\Iconv::iconv_get_encoding($type); }
|
||||
}
|
||||
if (!function_exists('iconv_set_encoding')) {
|
||||
function iconv_set_encoding($type, $charset) { return p\Iconv::iconv_set_encoding($type, $charset); }
|
||||
}
|
||||
if (!function_exists('iconv_mime_encode')) {
|
||||
function iconv_mime_encode($name, $value, $pref = null) { return p\Iconv::iconv_mime_encode($name, $value, $pref); }
|
||||
}
|
||||
if (!function_exists('iconv_mime_decode_headers')) {
|
||||
function iconv_mime_decode_headers($encodedHeaders, $mode = 0, $enc = null) { return p\Iconv::iconv_mime_decode_headers($encodedHeaders, $mode, $enc); }
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring')) {
|
||||
if (!function_exists('iconv_strlen')) {
|
||||
function iconv_strlen($s, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strlen($s, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_strpos')) {
|
||||
function iconv_strpos($s, $needle, $offset = 0, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strpos($s, $needle, $offset, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_strrpos')) {
|
||||
function iconv_strrpos($s, $needle, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strrpos($s, $needle, 0, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_substr')) {
|
||||
function iconv_substr($s, $start, $length = 2147483647, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_substr($s, $start, $length, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_mime_decode')) {
|
||||
function iconv_mime_decode($encodedHeaders, $mode = 0, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_decode_mimeheader($encodedHeaders, $mode, $enc); }
|
||||
}
|
||||
} else {
|
||||
if (!function_exists('iconv_strlen')) {
|
||||
if (extension_loaded('xml')) {
|
||||
function iconv_strlen($s, $enc = null) { return p\Iconv::strlen1($s, $enc); }
|
||||
} else {
|
||||
function iconv_strlen($s, $enc = null) { return p\Iconv::strlen2($s, $enc); }
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('iconv_strpos')) {
|
||||
function iconv_strpos($s, $needle, $offset = 0, $enc = null) { return p\Iconv::iconv_strpos($s, $needle, $offset, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_strrpos')) {
|
||||
function iconv_strrpos($s, $needle, $enc = null) { return p\Iconv::iconv_strrpos($s, $needle, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_substr')) {
|
||||
function iconv_substr($s, $start, $length = 2147483647, $enc = null) { return p\Iconv::iconv_substr($s, $start, $length, $enc); }
|
||||
}
|
||||
if (!function_exists('iconv_mime_decode')) {
|
||||
function iconv_mime_decode($encodedHeaders, $mode = 0, $enc = null) { return p\Iconv::iconv_mime_decode($encodedHeaders, $mode, $enc); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "symfony/polyfill-iconv",
|
||||
"type": "library",
|
||||
"description": "Symfony polyfill for the Iconv extension",
|
||||
"keywords": ["polyfill", "shim", "compatibility", "portable", "iconv"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Iconv\\": "" },
|
||||
"files": [ "bootstrap.php" ]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "For best performance"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.18-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Intl\Grapheme;
|
||||
|
||||
\define('SYMFONY_GRAPHEME_CLUSTER_RX', PCRE_VERSION >= '8.32' ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX);
|
||||
|
||||
/**
|
||||
* Partial intl implementation in pure PHP.
|
||||
*
|
||||
* Implemented:
|
||||
* - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8
|
||||
* - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string
|
||||
* - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack
|
||||
* - grapheme_strlen - Get string length in grapheme units
|
||||
* - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string
|
||||
* - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string
|
||||
* - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string
|
||||
* - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack
|
||||
* - grapheme_substr - Return part of a string
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Grapheme
|
||||
{
|
||||
// (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control])
|
||||
// This regular expression is a work around for http://bugs.exim.org/1279
|
||||
const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';
|
||||
|
||||
public static function grapheme_extract($s, $size, $type = GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0)
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70100 && 0 > $start) {
|
||||
$start = \strlen($s) + $start;
|
||||
}
|
||||
|
||||
if (!\is_scalar($s)) {
|
||||
$hasError = false;
|
||||
set_error_handler(function () use (&$hasError) { $hasError = true; });
|
||||
$next = substr($s, $start);
|
||||
restore_error_handler();
|
||||
if ($hasError) {
|
||||
substr($s, $start);
|
||||
$s = '';
|
||||
} else {
|
||||
$s = $next;
|
||||
}
|
||||
} else {
|
||||
$s = substr($s, $start);
|
||||
}
|
||||
$size = (int) $size;
|
||||
$type = (int) $type;
|
||||
$start = (int) $start;
|
||||
|
||||
if (!isset($s[0]) || 0 > $size || 0 > $start || 0 > $type || 2 < $type) {
|
||||
return false;
|
||||
}
|
||||
if (0 === $size) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$next = $start;
|
||||
|
||||
$s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
if (!isset($s[1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
$ret = '';
|
||||
|
||||
do {
|
||||
if (GRAPHEME_EXTR_COUNT === $type) {
|
||||
--$size;
|
||||
} elseif (GRAPHEME_EXTR_MAXBYTES === $type) {
|
||||
$size -= \strlen($s[$i]);
|
||||
} else {
|
||||
$size -= iconv_strlen($s[$i], 'UTF-8//IGNORE');
|
||||
}
|
||||
|
||||
if ($size >= 0) {
|
||||
$ret .= $s[$i];
|
||||
}
|
||||
} while (isset($s[++$i]) && $size > 0);
|
||||
|
||||
$next += \strlen($ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function grapheme_strlen($s)
|
||||
{
|
||||
preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len);
|
||||
|
||||
return 0 === $len && '' !== $s ? null : $len;
|
||||
}
|
||||
|
||||
public static function grapheme_substr($s, $start, $len = 2147483647)
|
||||
{
|
||||
preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s);
|
||||
|
||||
$slen = \count($s[0]);
|
||||
$start = (int) $start;
|
||||
|
||||
if (0 > $start) {
|
||||
$start += $slen;
|
||||
}
|
||||
if (0 > $start) {
|
||||
return false;
|
||||
}
|
||||
if ($start >= $slen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$rem = $slen - $start;
|
||||
|
||||
if (0 > $len) {
|
||||
$len += $rem;
|
||||
}
|
||||
if (0 === $len) {
|
||||
return '';
|
||||
}
|
||||
if (0 > $len) {
|
||||
return false;
|
||||
}
|
||||
if ($len > $rem) {
|
||||
$len = $rem;
|
||||
}
|
||||
|
||||
return implode('', \array_slice($s[0], $start, $len));
|
||||
}
|
||||
|
||||
public static function grapheme_strpos($s, $needle, $offset = 0)
|
||||
{
|
||||
return self::grapheme_position($s, $needle, $offset, 0);
|
||||
}
|
||||
|
||||
public static function grapheme_stripos($s, $needle, $offset = 0)
|
||||
{
|
||||
return self::grapheme_position($s, $needle, $offset, 1);
|
||||
}
|
||||
|
||||
public static function grapheme_strrpos($s, $needle, $offset = 0)
|
||||
{
|
||||
return self::grapheme_position($s, $needle, $offset, 2);
|
||||
}
|
||||
|
||||
public static function grapheme_strripos($s, $needle, $offset = 0)
|
||||
{
|
||||
return self::grapheme_position($s, $needle, $offset, 3);
|
||||
}
|
||||
|
||||
public static function grapheme_stristr($s, $needle, $beforeNeedle = false)
|
||||
{
|
||||
return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8');
|
||||
}
|
||||
|
||||
public static function grapheme_strstr($s, $needle, $beforeNeedle = false)
|
||||
{
|
||||
return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8');
|
||||
}
|
||||
|
||||
private static function grapheme_position($s, $needle, $offset, $mode)
|
||||
{
|
||||
$needle = (string) $needle;
|
||||
if (!preg_match('/./us', $needle)) {
|
||||
return false;
|
||||
}
|
||||
$s = (string) $s;
|
||||
if (!preg_match('/./us', $s)) {
|
||||
return false;
|
||||
}
|
||||
if ($offset > 0) {
|
||||
$s = self::grapheme_substr($s, $offset);
|
||||
} elseif ($offset < 0) {
|
||||
if (\PHP_VERSION_ID < 50535 || (50600 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 50621) || (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70006)) {
|
||||
$offset = 0;
|
||||
} elseif (2 > $mode) {
|
||||
$offset += self::grapheme_strlen($s);
|
||||
$s = self::grapheme_substr($s, $offset);
|
||||
if (0 > $offset) {
|
||||
$offset = 0;
|
||||
}
|
||||
} elseif (0 > $offset += self::grapheme_strlen($needle)) {
|
||||
$s = self::grapheme_substr($s, 0, $offset);
|
||||
$offset = 0;
|
||||
} else {
|
||||
$offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($mode) {
|
||||
case 0: $needle = iconv_strpos($s, $needle, 0, 'UTF-8'); break;
|
||||
case 1: $needle = mb_stripos($s, $needle, 0, 'UTF-8'); break;
|
||||
case 2: $needle = iconv_strrpos($s, $needle, 'UTF-8'); break;
|
||||
default: $needle = mb_strripos($s, $needle, 0, 'UTF-8'); break;
|
||||
}
|
||||
|
||||
return false !== $needle ? self::grapheme_strlen(iconv_substr($s, 0, $needle, 'UTF-8')) + $offset : false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-2019 Fabien Potencier
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,31 @@
|
||||
Symfony Polyfill / Intl: Grapheme
|
||||
=================================
|
||||
|
||||
This component provides a partial, native PHP implementation of the
|
||||
[Grapheme functions](https://php.net/intl.grapheme) from the
|
||||
[Intl](https://php.net/intl) extension.
|
||||
|
||||
- [`grapheme_extract`](https://php.net/grapheme_extract): Extract a sequence of grapheme
|
||||
clusters from a text buffer, which must be encoded in UTF-8
|
||||
- [`grapheme_stripos`](https://php.net/grapheme_stripos): Find position (in grapheme units)
|
||||
of first occurrence of a case-insensitive string
|
||||
- [`grapheme_stristr`](https://php.net/grapheme_stristr): Returns part of haystack string
|
||||
from the first occurrence of case-insensitive needle to the end of haystack
|
||||
- [`grapheme_strlen`](https://php.net/grapheme_strlen): Get string length in grapheme units
|
||||
- [`grapheme_strpos`](https://php.net/grapheme_strpos): Find position (in grapheme units)
|
||||
of first occurrence of a string
|
||||
- [`grapheme_strripos`](https://php.net/grapheme_strripos): Find position (in grapheme units)
|
||||
of last occurrence of a case-insensitive string
|
||||
- [`grapheme_strrpos`](https://php.net/grapheme_strrpos): Find position (in grapheme units)
|
||||
of last occurrence of a string
|
||||
- [`grapheme_strstr`](https://php.net/grapheme_strstr): Returns part of haystack string from
|
||||
the first occurrence of needle to the end of haystack
|
||||
- [`grapheme_substr`](https://php.net/grapheme_substr): Return part of a string
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Intl\Grapheme as p;
|
||||
|
||||
if (extension_loaded('intl')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('GRAPHEME_EXTR_COUNT')) {
|
||||
define('GRAPHEME_EXTR_COUNT', 0);
|
||||
}
|
||||
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
|
||||
define('GRAPHEME_EXTR_MAXBYTES', 1);
|
||||
}
|
||||
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
|
||||
define('GRAPHEME_EXTR_MAXCHARS', 2);
|
||||
}
|
||||
|
||||
if (!function_exists('grapheme_extract')) {
|
||||
function grapheme_extract($s, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($s, $size, $type, $start, $next); }
|
||||
}
|
||||
if (!function_exists('grapheme_stripos')) {
|
||||
function grapheme_stripos($s, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($s, $needle, $offset); }
|
||||
}
|
||||
if (!function_exists('grapheme_stristr')) {
|
||||
function grapheme_stristr($s, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($s, $needle, $beforeNeedle); }
|
||||
}
|
||||
if (!function_exists('grapheme_strlen')) {
|
||||
function grapheme_strlen($s) { return p\Grapheme::grapheme_strlen($s); }
|
||||
}
|
||||
if (!function_exists('grapheme_strpos')) {
|
||||
function grapheme_strpos($s, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($s, $needle, $offset); }
|
||||
}
|
||||
if (!function_exists('grapheme_strripos')) {
|
||||
function grapheme_strripos($s, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($s, $needle, $offset); }
|
||||
}
|
||||
if (!function_exists('grapheme_strrpos')) {
|
||||
function grapheme_strrpos($s, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($s, $needle, $offset); }
|
||||
}
|
||||
if (!function_exists('grapheme_strstr')) {
|
||||
function grapheme_strstr($s, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($s, $needle, $beforeNeedle); }
|
||||
}
|
||||
if (!function_exists('grapheme_substr')) {
|
||||
function grapheme_substr($s, $start, $len = 2147483647) { return p\Grapheme::grapheme_substr($s, $start, $len); }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"type": "library",
|
||||
"description": "Symfony polyfill for intl's grapheme_* functions",
|
||||
"keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" },
|
||||
"files": [ "bootstrap.php" ]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.18-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-2019 Fabien Potencier
|
||||
|
||||
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.
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Intl\Normalizer;
|
||||
|
||||
/**
|
||||
* Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension.
|
||||
*
|
||||
* It has been validated with Unicode 6.3 Normalization Conformance Test.
|
||||
* See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Normalizer
|
||||
{
|
||||
const FORM_D = \Normalizer::FORM_D;
|
||||
const FORM_KD = \Normalizer::FORM_KD;
|
||||
const FORM_C = \Normalizer::FORM_C;
|
||||
const FORM_KC = \Normalizer::FORM_KC;
|
||||
const NFD = \Normalizer::NFD;
|
||||
const NFKD = \Normalizer::NFKD;
|
||||
const NFC = \Normalizer::NFC;
|
||||
const NFKC = \Normalizer::NFKC;
|
||||
|
||||
private static $C;
|
||||
private static $D;
|
||||
private static $KD;
|
||||
private static $cC;
|
||||
private static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
|
||||
private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
|
||||
|
||||
public static function isNormalized($s, $form = self::NFC)
|
||||
{
|
||||
if (!\in_array($form, array(self::NFD, self::NFKD, self::NFC, self::NFKC))) {
|
||||
return false;
|
||||
}
|
||||
$s = (string) $s;
|
||||
if (!isset($s[strspn($s, self::$ASCII)])) {
|
||||
return true;
|
||||
}
|
||||
if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self::normalize($s, $form) === $s;
|
||||
}
|
||||
|
||||
public static function normalize($s, $form = self::NFC)
|
||||
{
|
||||
$s = (string) $s;
|
||||
if (!preg_match('//u', $s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($form) {
|
||||
case self::NFC: $C = true; $K = false; break;
|
||||
case self::NFD: $C = false; $K = false; break;
|
||||
case self::NFKC: $C = true; $K = true; break;
|
||||
case self::NFKD: $C = false; $K = true; break;
|
||||
default:
|
||||
if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) {
|
||||
return $s;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('' === $s) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($K && null === self::$KD) {
|
||||
self::$KD = self::getData('compatibilityDecomposition');
|
||||
}
|
||||
|
||||
if (null === self::$D) {
|
||||
self::$D = self::getData('canonicalDecomposition');
|
||||
self::$cC = self::getData('combiningClass');
|
||||
}
|
||||
|
||||
if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) {
|
||||
mb_internal_encoding('8bit');
|
||||
}
|
||||
|
||||
$r = self::decompose($s, $K);
|
||||
|
||||
if ($C) {
|
||||
if (null === self::$C) {
|
||||
self::$C = self::getData('canonicalComposition');
|
||||
}
|
||||
|
||||
$r = self::recompose($r);
|
||||
}
|
||||
if (null !== $mbEncoding) {
|
||||
mb_internal_encoding($mbEncoding);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
private static function recompose($s)
|
||||
{
|
||||
$ASCII = self::$ASCII;
|
||||
$compMap = self::$C;
|
||||
$combClass = self::$cC;
|
||||
$ulenMask = self::$ulenMask;
|
||||
|
||||
$result = $tail = '';
|
||||
|
||||
$i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"];
|
||||
$len = \strlen($s);
|
||||
|
||||
$lastUchr = substr($s, 0, $i);
|
||||
$lastUcls = isset($combClass[$lastUchr]) ? 256 : 0;
|
||||
|
||||
while ($i < $len) {
|
||||
if ($s[$i] < "\x80") {
|
||||
// ASCII chars
|
||||
|
||||
if ($tail) {
|
||||
$lastUchr .= $tail;
|
||||
$tail = '';
|
||||
}
|
||||
|
||||
if ($j = strspn($s, $ASCII, $i + 1)) {
|
||||
$lastUchr .= substr($s, $i, $j);
|
||||
$i += $j;
|
||||
}
|
||||
|
||||
$result .= $lastUchr;
|
||||
$lastUchr = $s[$i];
|
||||
$lastUcls = 0;
|
||||
++$i;
|
||||
continue;
|
||||
}
|
||||
|
||||
$ulen = $ulenMask[$s[$i] & "\xF0"];
|
||||
$uchr = substr($s, $i, $ulen);
|
||||
|
||||
if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr
|
||||
|| $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr
|
||||
|| $lastUcls) {
|
||||
// Table lookup and combining chars composition
|
||||
|
||||
$ucls = isset($combClass[$uchr]) ? $combClass[$uchr] : 0;
|
||||
|
||||
if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) {
|
||||
$lastUchr = $compMap[$lastUchr.$uchr];
|
||||
} elseif ($lastUcls = $ucls) {
|
||||
$tail .= $uchr;
|
||||
} else {
|
||||
if ($tail) {
|
||||
$lastUchr .= $tail;
|
||||
$tail = '';
|
||||
}
|
||||
|
||||
$result .= $lastUchr;
|
||||
$lastUchr = $uchr;
|
||||
}
|
||||
} else {
|
||||
// Hangul chars
|
||||
|
||||
$L = \ord($lastUchr[2]) - 0x80;
|
||||
$V = \ord($uchr[2]) - 0xA1;
|
||||
$T = 0;
|
||||
|
||||
$uchr = substr($s, $i + $ulen, 3);
|
||||
|
||||
if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") {
|
||||
$T = \ord($uchr[2]) - 0xA7;
|
||||
0 > $T && $T += 0x40;
|
||||
$ulen += 3;
|
||||
}
|
||||
|
||||
$L = 0xAC00 + ($L * 21 + $V) * 28 + $T;
|
||||
$lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F);
|
||||
}
|
||||
|
||||
$i += $ulen;
|
||||
}
|
||||
|
||||
return $result.$lastUchr.$tail;
|
||||
}
|
||||
|
||||
private static function decompose($s, $c)
|
||||
{
|
||||
$result = '';
|
||||
|
||||
$ASCII = self::$ASCII;
|
||||
$decompMap = self::$D;
|
||||
$combClass = self::$cC;
|
||||
$ulenMask = self::$ulenMask;
|
||||
if ($c) {
|
||||
$compatMap = self::$KD;
|
||||
}
|
||||
|
||||
$c = array();
|
||||
$i = 0;
|
||||
$len = \strlen($s);
|
||||
|
||||
while ($i < $len) {
|
||||
if ($s[$i] < "\x80") {
|
||||
// ASCII chars
|
||||
|
||||
if ($c) {
|
||||
ksort($c);
|
||||
$result .= implode('', $c);
|
||||
$c = array();
|
||||
}
|
||||
|
||||
$j = 1 + strspn($s, $ASCII, $i + 1);
|
||||
$result .= substr($s, $i, $j);
|
||||
$i += $j;
|
||||
continue;
|
||||
}
|
||||
|
||||
$ulen = $ulenMask[$s[$i] & "\xF0"];
|
||||
$uchr = substr($s, $i, $ulen);
|
||||
$i += $ulen;
|
||||
|
||||
if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) {
|
||||
// Table lookup
|
||||
|
||||
if ($uchr !== $j = isset($compatMap[$uchr]) ? $compatMap[$uchr] : (isset($decompMap[$uchr]) ? $decompMap[$uchr] : $uchr)) {
|
||||
$uchr = $j;
|
||||
|
||||
$j = \strlen($uchr);
|
||||
$ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"];
|
||||
|
||||
if ($ulen != $j) {
|
||||
// Put trailing chars in $s
|
||||
|
||||
$j -= $ulen;
|
||||
$i -= $j;
|
||||
|
||||
if (0 > $i) {
|
||||
$s = str_repeat(' ', -$i).$s;
|
||||
$len -= $i;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
while ($j--) {
|
||||
$s[$i + $j] = $uchr[$ulen + $j];
|
||||
}
|
||||
|
||||
$uchr = substr($uchr, 0, $ulen);
|
||||
}
|
||||
}
|
||||
if (isset($combClass[$uchr])) {
|
||||
// Combining chars, for sorting
|
||||
|
||||
if (!isset($c[$combClass[$uchr]])) {
|
||||
$c[$combClass[$uchr]] = '';
|
||||
}
|
||||
$c[$combClass[$uchr]] .= $uchr;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Hangul chars
|
||||
|
||||
$uchr = unpack('C*', $uchr);
|
||||
$j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80;
|
||||
|
||||
$uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588))
|
||||
."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28));
|
||||
|
||||
if ($j %= 28) {
|
||||
$uchr .= $j < 25
|
||||
? ("\xE1\x86".\chr(0xA7 + $j))
|
||||
: ("\xE1\x87".\chr(0x67 + $j));
|
||||
}
|
||||
}
|
||||
if ($c) {
|
||||
ksort($c);
|
||||
$result .= implode('', $c);
|
||||
$c = array();
|
||||
}
|
||||
|
||||
$result .= $uchr;
|
||||
}
|
||||
|
||||
if ($c) {
|
||||
ksort($c);
|
||||
$result .= implode('', $c);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function getData($file)
|
||||
{
|
||||
if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
|
||||
return require $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
Symfony Polyfill / Intl: Normalizer
|
||||
===================================
|
||||
|
||||
This component provides a fallback implementation for the
|
||||
[`Normalizer`](https://php.net/Normalizer) class provided
|
||||
by the [Intl](https://php.net/intl) extension.
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer
|
||||
{
|
||||
/**
|
||||
* @deprecated since ICU 56 and removed in PHP 8
|
||||
*/
|
||||
const NONE = 1;
|
||||
const FORM_D = 2;
|
||||
const FORM_KD = 3;
|
||||
const FORM_C = 4;
|
||||
const FORM_KC = 5;
|
||||
const NFD = 2;
|
||||
const NFKD = 3;
|
||||
const NFC = 4;
|
||||
const NFKC = 5;
|
||||
}
|
||||
+945
@@ -0,0 +1,945 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'À' => 'À',
|
||||
'Á' => 'Á',
|
||||
'Â' => 'Â',
|
||||
'Ã' => 'Ã',
|
||||
'Ä' => 'Ä',
|
||||
'Å' => 'Å',
|
||||
'Ç' => 'Ç',
|
||||
'È' => 'È',
|
||||
'É' => 'É',
|
||||
'Ê' => 'Ê',
|
||||
'Ë' => 'Ë',
|
||||
'Ì' => 'Ì',
|
||||
'Í' => 'Í',
|
||||
'Î' => 'Î',
|
||||
'Ï' => 'Ï',
|
||||
'Ñ' => 'Ñ',
|
||||
'Ò' => 'Ò',
|
||||
'Ó' => 'Ó',
|
||||
'Ô' => 'Ô',
|
||||
'Õ' => 'Õ',
|
||||
'Ö' => 'Ö',
|
||||
'Ù' => 'Ù',
|
||||
'Ú' => 'Ú',
|
||||
'Û' => 'Û',
|
||||
'Ü' => 'Ü',
|
||||
'Ý' => 'Ý',
|
||||
'à' => 'à',
|
||||
'á' => 'á',
|
||||
'â' => 'â',
|
||||
'ã' => 'ã',
|
||||
'ä' => 'ä',
|
||||
'å' => 'å',
|
||||
'ç' => 'ç',
|
||||
'è' => 'è',
|
||||
'é' => 'é',
|
||||
'ê' => 'ê',
|
||||
'ë' => 'ë',
|
||||
'ì' => 'ì',
|
||||
'í' => 'í',
|
||||
'î' => 'î',
|
||||
'ï' => 'ï',
|
||||
'ñ' => 'ñ',
|
||||
'ò' => 'ò',
|
||||
'ó' => 'ó',
|
||||
'ô' => 'ô',
|
||||
'õ' => 'õ',
|
||||
'ö' => 'ö',
|
||||
'ù' => 'ù',
|
||||
'ú' => 'ú',
|
||||
'û' => 'û',
|
||||
'ü' => 'ü',
|
||||
'ý' => 'ý',
|
||||
'ÿ' => 'ÿ',
|
||||
'Ā' => 'Ā',
|
||||
'ā' => 'ā',
|
||||
'Ă' => 'Ă',
|
||||
'ă' => 'ă',
|
||||
'Ą' => 'Ą',
|
||||
'ą' => 'ą',
|
||||
'Ć' => 'Ć',
|
||||
'ć' => 'ć',
|
||||
'Ĉ' => 'Ĉ',
|
||||
'ĉ' => 'ĉ',
|
||||
'Ċ' => 'Ċ',
|
||||
'ċ' => 'ċ',
|
||||
'Č' => 'Č',
|
||||
'č' => 'č',
|
||||
'Ď' => 'Ď',
|
||||
'ď' => 'ď',
|
||||
'Ē' => 'Ē',
|
||||
'ē' => 'ē',
|
||||
'Ĕ' => 'Ĕ',
|
||||
'ĕ' => 'ĕ',
|
||||
'Ė' => 'Ė',
|
||||
'ė' => 'ė',
|
||||
'Ę' => 'Ę',
|
||||
'ę' => 'ę',
|
||||
'Ě' => 'Ě',
|
||||
'ě' => 'ě',
|
||||
'Ĝ' => 'Ĝ',
|
||||
'ĝ' => 'ĝ',
|
||||
'Ğ' => 'Ğ',
|
||||
'ğ' => 'ğ',
|
||||
'Ġ' => 'Ġ',
|
||||
'ġ' => 'ġ',
|
||||
'Ģ' => 'Ģ',
|
||||
'ģ' => 'ģ',
|
||||
'Ĥ' => 'Ĥ',
|
||||
'ĥ' => 'ĥ',
|
||||
'Ĩ' => 'Ĩ',
|
||||
'ĩ' => 'ĩ',
|
||||
'Ī' => 'Ī',
|
||||
'ī' => 'ī',
|
||||
'Ĭ' => 'Ĭ',
|
||||
'ĭ' => 'ĭ',
|
||||
'Į' => 'Į',
|
||||
'į' => 'į',
|
||||
'İ' => 'İ',
|
||||
'Ĵ' => 'Ĵ',
|
||||
'ĵ' => 'ĵ',
|
||||
'Ķ' => 'Ķ',
|
||||
'ķ' => 'ķ',
|
||||
'Ĺ' => 'Ĺ',
|
||||
'ĺ' => 'ĺ',
|
||||
'Ļ' => 'Ļ',
|
||||
'ļ' => 'ļ',
|
||||
'Ľ' => 'Ľ',
|
||||
'ľ' => 'ľ',
|
||||
'Ń' => 'Ń',
|
||||
'ń' => 'ń',
|
||||
'Ņ' => 'Ņ',
|
||||
'ņ' => 'ņ',
|
||||
'Ň' => 'Ň',
|
||||
'ň' => 'ň',
|
||||
'Ō' => 'Ō',
|
||||
'ō' => 'ō',
|
||||
'Ŏ' => 'Ŏ',
|
||||
'ŏ' => 'ŏ',
|
||||
'Ő' => 'Ő',
|
||||
'ő' => 'ő',
|
||||
'Ŕ' => 'Ŕ',
|
||||
'ŕ' => 'ŕ',
|
||||
'Ŗ' => 'Ŗ',
|
||||
'ŗ' => 'ŗ',
|
||||
'Ř' => 'Ř',
|
||||
'ř' => 'ř',
|
||||
'Ś' => 'Ś',
|
||||
'ś' => 'ś',
|
||||
'Ŝ' => 'Ŝ',
|
||||
'ŝ' => 'ŝ',
|
||||
'Ş' => 'Ş',
|
||||
'ş' => 'ş',
|
||||
'Š' => 'Š',
|
||||
'š' => 'š',
|
||||
'Ţ' => 'Ţ',
|
||||
'ţ' => 'ţ',
|
||||
'Ť' => 'Ť',
|
||||
'ť' => 'ť',
|
||||
'Ũ' => 'Ũ',
|
||||
'ũ' => 'ũ',
|
||||
'Ū' => 'Ū',
|
||||
'ū' => 'ū',
|
||||
'Ŭ' => 'Ŭ',
|
||||
'ŭ' => 'ŭ',
|
||||
'Ů' => 'Ů',
|
||||
'ů' => 'ů',
|
||||
'Ű' => 'Ű',
|
||||
'ű' => 'ű',
|
||||
'Ų' => 'Ų',
|
||||
'ų' => 'ų',
|
||||
'Ŵ' => 'Ŵ',
|
||||
'ŵ' => 'ŵ',
|
||||
'Ŷ' => 'Ŷ',
|
||||
'ŷ' => 'ŷ',
|
||||
'Ÿ' => 'Ÿ',
|
||||
'Ź' => 'Ź',
|
||||
'ź' => 'ź',
|
||||
'Ż' => 'Ż',
|
||||
'ż' => 'ż',
|
||||
'Ž' => 'Ž',
|
||||
'ž' => 'ž',
|
||||
'Ơ' => 'Ơ',
|
||||
'ơ' => 'ơ',
|
||||
'Ư' => 'Ư',
|
||||
'ư' => 'ư',
|
||||
'Ǎ' => 'Ǎ',
|
||||
'ǎ' => 'ǎ',
|
||||
'Ǐ' => 'Ǐ',
|
||||
'ǐ' => 'ǐ',
|
||||
'Ǒ' => 'Ǒ',
|
||||
'ǒ' => 'ǒ',
|
||||
'Ǔ' => 'Ǔ',
|
||||
'ǔ' => 'ǔ',
|
||||
'Ǖ' => 'Ǖ',
|
||||
'ǖ' => 'ǖ',
|
||||
'Ǘ' => 'Ǘ',
|
||||
'ǘ' => 'ǘ',
|
||||
'Ǚ' => 'Ǚ',
|
||||
'ǚ' => 'ǚ',
|
||||
'Ǜ' => 'Ǜ',
|
||||
'ǜ' => 'ǜ',
|
||||
'Ǟ' => 'Ǟ',
|
||||
'ǟ' => 'ǟ',
|
||||
'Ǡ' => 'Ǡ',
|
||||
'ǡ' => 'ǡ',
|
||||
'Ǣ' => 'Ǣ',
|
||||
'ǣ' => 'ǣ',
|
||||
'Ǧ' => 'Ǧ',
|
||||
'ǧ' => 'ǧ',
|
||||
'Ǩ' => 'Ǩ',
|
||||
'ǩ' => 'ǩ',
|
||||
'Ǫ' => 'Ǫ',
|
||||
'ǫ' => 'ǫ',
|
||||
'Ǭ' => 'Ǭ',
|
||||
'ǭ' => 'ǭ',
|
||||
'Ǯ' => 'Ǯ',
|
||||
'ǯ' => 'ǯ',
|
||||
'ǰ' => 'ǰ',
|
||||
'Ǵ' => 'Ǵ',
|
||||
'ǵ' => 'ǵ',
|
||||
'Ǹ' => 'Ǹ',
|
||||
'ǹ' => 'ǹ',
|
||||
'Ǻ' => 'Ǻ',
|
||||
'ǻ' => 'ǻ',
|
||||
'Ǽ' => 'Ǽ',
|
||||
'ǽ' => 'ǽ',
|
||||
'Ǿ' => 'Ǿ',
|
||||
'ǿ' => 'ǿ',
|
||||
'Ȁ' => 'Ȁ',
|
||||
'ȁ' => 'ȁ',
|
||||
'Ȃ' => 'Ȃ',
|
||||
'ȃ' => 'ȃ',
|
||||
'Ȅ' => 'Ȅ',
|
||||
'ȅ' => 'ȅ',
|
||||
'Ȇ' => 'Ȇ',
|
||||
'ȇ' => 'ȇ',
|
||||
'Ȉ' => 'Ȉ',
|
||||
'ȉ' => 'ȉ',
|
||||
'Ȋ' => 'Ȋ',
|
||||
'ȋ' => 'ȋ',
|
||||
'Ȍ' => 'Ȍ',
|
||||
'ȍ' => 'ȍ',
|
||||
'Ȏ' => 'Ȏ',
|
||||
'ȏ' => 'ȏ',
|
||||
'Ȑ' => 'Ȑ',
|
||||
'ȑ' => 'ȑ',
|
||||
'Ȓ' => 'Ȓ',
|
||||
'ȓ' => 'ȓ',
|
||||
'Ȕ' => 'Ȕ',
|
||||
'ȕ' => 'ȕ',
|
||||
'Ȗ' => 'Ȗ',
|
||||
'ȗ' => 'ȗ',
|
||||
'Ș' => 'Ș',
|
||||
'ș' => 'ș',
|
||||
'Ț' => 'Ț',
|
||||
'ț' => 'ț',
|
||||
'Ȟ' => 'Ȟ',
|
||||
'ȟ' => 'ȟ',
|
||||
'Ȧ' => 'Ȧ',
|
||||
'ȧ' => 'ȧ',
|
||||
'Ȩ' => 'Ȩ',
|
||||
'ȩ' => 'ȩ',
|
||||
'Ȫ' => 'Ȫ',
|
||||
'ȫ' => 'ȫ',
|
||||
'Ȭ' => 'Ȭ',
|
||||
'ȭ' => 'ȭ',
|
||||
'Ȯ' => 'Ȯ',
|
||||
'ȯ' => 'ȯ',
|
||||
'Ȱ' => 'Ȱ',
|
||||
'ȱ' => 'ȱ',
|
||||
'Ȳ' => 'Ȳ',
|
||||
'ȳ' => 'ȳ',
|
||||
'΅' => '΅',
|
||||
'Ά' => 'Ά',
|
||||
'Έ' => 'Έ',
|
||||
'Ή' => 'Ή',
|
||||
'Ί' => 'Ί',
|
||||
'Ό' => 'Ό',
|
||||
'Ύ' => 'Ύ',
|
||||
'Ώ' => 'Ώ',
|
||||
'ΐ' => 'ΐ',
|
||||
'Ϊ' => 'Ϊ',
|
||||
'Ϋ' => 'Ϋ',
|
||||
'ά' => 'ά',
|
||||
'έ' => 'έ',
|
||||
'ή' => 'ή',
|
||||
'ί' => 'ί',
|
||||
'ΰ' => 'ΰ',
|
||||
'ϊ' => 'ϊ',
|
||||
'ϋ' => 'ϋ',
|
||||
'ό' => 'ό',
|
||||
'ύ' => 'ύ',
|
||||
'ώ' => 'ώ',
|
||||
'ϓ' => 'ϓ',
|
||||
'ϔ' => 'ϔ',
|
||||
'Ѐ' => 'Ѐ',
|
||||
'Ё' => 'Ё',
|
||||
'Ѓ' => 'Ѓ',
|
||||
'Ї' => 'Ї',
|
||||
'Ќ' => 'Ќ',
|
||||
'Ѝ' => 'Ѝ',
|
||||
'Ў' => 'Ў',
|
||||
'Й' => 'Й',
|
||||
'й' => 'й',
|
||||
'ѐ' => 'ѐ',
|
||||
'ё' => 'ё',
|
||||
'ѓ' => 'ѓ',
|
||||
'ї' => 'ї',
|
||||
'ќ' => 'ќ',
|
||||
'ѝ' => 'ѝ',
|
||||
'ў' => 'ў',
|
||||
'Ѷ' => 'Ѷ',
|
||||
'ѷ' => 'ѷ',
|
||||
'Ӂ' => 'Ӂ',
|
||||
'ӂ' => 'ӂ',
|
||||
'Ӑ' => 'Ӑ',
|
||||
'ӑ' => 'ӑ',
|
||||
'Ӓ' => 'Ӓ',
|
||||
'ӓ' => 'ӓ',
|
||||
'Ӗ' => 'Ӗ',
|
||||
'ӗ' => 'ӗ',
|
||||
'Ӛ' => 'Ӛ',
|
||||
'ӛ' => 'ӛ',
|
||||
'Ӝ' => 'Ӝ',
|
||||
'ӝ' => 'ӝ',
|
||||
'Ӟ' => 'Ӟ',
|
||||
'ӟ' => 'ӟ',
|
||||
'Ӣ' => 'Ӣ',
|
||||
'ӣ' => 'ӣ',
|
||||
'Ӥ' => 'Ӥ',
|
||||
'ӥ' => 'ӥ',
|
||||
'Ӧ' => 'Ӧ',
|
||||
'ӧ' => 'ӧ',
|
||||
'Ӫ' => 'Ӫ',
|
||||
'ӫ' => 'ӫ',
|
||||
'Ӭ' => 'Ӭ',
|
||||
'ӭ' => 'ӭ',
|
||||
'Ӯ' => 'Ӯ',
|
||||
'ӯ' => 'ӯ',
|
||||
'Ӱ' => 'Ӱ',
|
||||
'ӱ' => 'ӱ',
|
||||
'Ӳ' => 'Ӳ',
|
||||
'ӳ' => 'ӳ',
|
||||
'Ӵ' => 'Ӵ',
|
||||
'ӵ' => 'ӵ',
|
||||
'Ӹ' => 'Ӹ',
|
||||
'ӹ' => 'ӹ',
|
||||
'آ' => 'آ',
|
||||
'أ' => 'أ',
|
||||
'ؤ' => 'ؤ',
|
||||
'إ' => 'إ',
|
||||
'ئ' => 'ئ',
|
||||
'ۀ' => 'ۀ',
|
||||
'ۂ' => 'ۂ',
|
||||
'ۓ' => 'ۓ',
|
||||
'ऩ' => 'ऩ',
|
||||
'ऱ' => 'ऱ',
|
||||
'ऴ' => 'ऴ',
|
||||
'ো' => 'ো',
|
||||
'ৌ' => 'ৌ',
|
||||
'ୈ' => 'ୈ',
|
||||
'ୋ' => 'ୋ',
|
||||
'ୌ' => 'ୌ',
|
||||
'ஔ' => 'ஔ',
|
||||
'ொ' => 'ொ',
|
||||
'ோ' => 'ோ',
|
||||
'ௌ' => 'ௌ',
|
||||
'ై' => 'ై',
|
||||
'ೀ' => 'ೀ',
|
||||
'ೇ' => 'ೇ',
|
||||
'ೈ' => 'ೈ',
|
||||
'ೊ' => 'ೊ',
|
||||
'ೋ' => 'ೋ',
|
||||
'ൊ' => 'ൊ',
|
||||
'ോ' => 'ോ',
|
||||
'ൌ' => 'ൌ',
|
||||
'ේ' => 'ේ',
|
||||
'ො' => 'ො',
|
||||
'ෝ' => 'ෝ',
|
||||
'ෞ' => 'ෞ',
|
||||
'ဦ' => 'ဦ',
|
||||
'ᬆ' => 'ᬆ',
|
||||
'ᬈ' => 'ᬈ',
|
||||
'ᬊ' => 'ᬊ',
|
||||
'ᬌ' => 'ᬌ',
|
||||
'ᬎ' => 'ᬎ',
|
||||
'ᬒ' => 'ᬒ',
|
||||
'ᬻ' => 'ᬻ',
|
||||
'ᬽ' => 'ᬽ',
|
||||
'ᭀ' => 'ᭀ',
|
||||
'ᭁ' => 'ᭁ',
|
||||
'ᭃ' => 'ᭃ',
|
||||
'Ḁ' => 'Ḁ',
|
||||
'ḁ' => 'ḁ',
|
||||
'Ḃ' => 'Ḃ',
|
||||
'ḃ' => 'ḃ',
|
||||
'Ḅ' => 'Ḅ',
|
||||
'ḅ' => 'ḅ',
|
||||
'Ḇ' => 'Ḇ',
|
||||
'ḇ' => 'ḇ',
|
||||
'Ḉ' => 'Ḉ',
|
||||
'ḉ' => 'ḉ',
|
||||
'Ḋ' => 'Ḋ',
|
||||
'ḋ' => 'ḋ',
|
||||
'Ḍ' => 'Ḍ',
|
||||
'ḍ' => 'ḍ',
|
||||
'Ḏ' => 'Ḏ',
|
||||
'ḏ' => 'ḏ',
|
||||
'Ḑ' => 'Ḑ',
|
||||
'ḑ' => 'ḑ',
|
||||
'Ḓ' => 'Ḓ',
|
||||
'ḓ' => 'ḓ',
|
||||
'Ḕ' => 'Ḕ',
|
||||
'ḕ' => 'ḕ',
|
||||
'Ḗ' => 'Ḗ',
|
||||
'ḗ' => 'ḗ',
|
||||
'Ḙ' => 'Ḙ',
|
||||
'ḙ' => 'ḙ',
|
||||
'Ḛ' => 'Ḛ',
|
||||
'ḛ' => 'ḛ',
|
||||
'Ḝ' => 'Ḝ',
|
||||
'ḝ' => 'ḝ',
|
||||
'Ḟ' => 'Ḟ',
|
||||
'ḟ' => 'ḟ',
|
||||
'Ḡ' => 'Ḡ',
|
||||
'ḡ' => 'ḡ',
|
||||
'Ḣ' => 'Ḣ',
|
||||
'ḣ' => 'ḣ',
|
||||
'Ḥ' => 'Ḥ',
|
||||
'ḥ' => 'ḥ',
|
||||
'Ḧ' => 'Ḧ',
|
||||
'ḧ' => 'ḧ',
|
||||
'Ḩ' => 'Ḩ',
|
||||
'ḩ' => 'ḩ',
|
||||
'Ḫ' => 'Ḫ',
|
||||
'ḫ' => 'ḫ',
|
||||
'Ḭ' => 'Ḭ',
|
||||
'ḭ' => 'ḭ',
|
||||
'Ḯ' => 'Ḯ',
|
||||
'ḯ' => 'ḯ',
|
||||
'Ḱ' => 'Ḱ',
|
||||
'ḱ' => 'ḱ',
|
||||
'Ḳ' => 'Ḳ',
|
||||
'ḳ' => 'ḳ',
|
||||
'Ḵ' => 'Ḵ',
|
||||
'ḵ' => 'ḵ',
|
||||
'Ḷ' => 'Ḷ',
|
||||
'ḷ' => 'ḷ',
|
||||
'Ḹ' => 'Ḹ',
|
||||
'ḹ' => 'ḹ',
|
||||
'Ḻ' => 'Ḻ',
|
||||
'ḻ' => 'ḻ',
|
||||
'Ḽ' => 'Ḽ',
|
||||
'ḽ' => 'ḽ',
|
||||
'Ḿ' => 'Ḿ',
|
||||
'ḿ' => 'ḿ',
|
||||
'Ṁ' => 'Ṁ',
|
||||
'ṁ' => 'ṁ',
|
||||
'Ṃ' => 'Ṃ',
|
||||
'ṃ' => 'ṃ',
|
||||
'Ṅ' => 'Ṅ',
|
||||
'ṅ' => 'ṅ',
|
||||
'Ṇ' => 'Ṇ',
|
||||
'ṇ' => 'ṇ',
|
||||
'Ṉ' => 'Ṉ',
|
||||
'ṉ' => 'ṉ',
|
||||
'Ṋ' => 'Ṋ',
|
||||
'ṋ' => 'ṋ',
|
||||
'Ṍ' => 'Ṍ',
|
||||
'ṍ' => 'ṍ',
|
||||
'Ṏ' => 'Ṏ',
|
||||
'ṏ' => 'ṏ',
|
||||
'Ṑ' => 'Ṑ',
|
||||
'ṑ' => 'ṑ',
|
||||
'Ṓ' => 'Ṓ',
|
||||
'ṓ' => 'ṓ',
|
||||
'Ṕ' => 'Ṕ',
|
||||
'ṕ' => 'ṕ',
|
||||
'Ṗ' => 'Ṗ',
|
||||
'ṗ' => 'ṗ',
|
||||
'Ṙ' => 'Ṙ',
|
||||
'ṙ' => 'ṙ',
|
||||
'Ṛ' => 'Ṛ',
|
||||
'ṛ' => 'ṛ',
|
||||
'Ṝ' => 'Ṝ',
|
||||
'ṝ' => 'ṝ',
|
||||
'Ṟ' => 'Ṟ',
|
||||
'ṟ' => 'ṟ',
|
||||
'Ṡ' => 'Ṡ',
|
||||
'ṡ' => 'ṡ',
|
||||
'Ṣ' => 'Ṣ',
|
||||
'ṣ' => 'ṣ',
|
||||
'Ṥ' => 'Ṥ',
|
||||
'ṥ' => 'ṥ',
|
||||
'Ṧ' => 'Ṧ',
|
||||
'ṧ' => 'ṧ',
|
||||
'Ṩ' => 'Ṩ',
|
||||
'ṩ' => 'ṩ',
|
||||
'Ṫ' => 'Ṫ',
|
||||
'ṫ' => 'ṫ',
|
||||
'Ṭ' => 'Ṭ',
|
||||
'ṭ' => 'ṭ',
|
||||
'Ṯ' => 'Ṯ',
|
||||
'ṯ' => 'ṯ',
|
||||
'Ṱ' => 'Ṱ',
|
||||
'ṱ' => 'ṱ',
|
||||
'Ṳ' => 'Ṳ',
|
||||
'ṳ' => 'ṳ',
|
||||
'Ṵ' => 'Ṵ',
|
||||
'ṵ' => 'ṵ',
|
||||
'Ṷ' => 'Ṷ',
|
||||
'ṷ' => 'ṷ',
|
||||
'Ṹ' => 'Ṹ',
|
||||
'ṹ' => 'ṹ',
|
||||
'Ṻ' => 'Ṻ',
|
||||
'ṻ' => 'ṻ',
|
||||
'Ṽ' => 'Ṽ',
|
||||
'ṽ' => 'ṽ',
|
||||
'Ṿ' => 'Ṿ',
|
||||
'ṿ' => 'ṿ',
|
||||
'Ẁ' => 'Ẁ',
|
||||
'ẁ' => 'ẁ',
|
||||
'Ẃ' => 'Ẃ',
|
||||
'ẃ' => 'ẃ',
|
||||
'Ẅ' => 'Ẅ',
|
||||
'ẅ' => 'ẅ',
|
||||
'Ẇ' => 'Ẇ',
|
||||
'ẇ' => 'ẇ',
|
||||
'Ẉ' => 'Ẉ',
|
||||
'ẉ' => 'ẉ',
|
||||
'Ẋ' => 'Ẋ',
|
||||
'ẋ' => 'ẋ',
|
||||
'Ẍ' => 'Ẍ',
|
||||
'ẍ' => 'ẍ',
|
||||
'Ẏ' => 'Ẏ',
|
||||
'ẏ' => 'ẏ',
|
||||
'Ẑ' => 'Ẑ',
|
||||
'ẑ' => 'ẑ',
|
||||
'Ẓ' => 'Ẓ',
|
||||
'ẓ' => 'ẓ',
|
||||
'Ẕ' => 'Ẕ',
|
||||
'ẕ' => 'ẕ',
|
||||
'ẖ' => 'ẖ',
|
||||
'ẗ' => 'ẗ',
|
||||
'ẘ' => 'ẘ',
|
||||
'ẙ' => 'ẙ',
|
||||
'ẛ' => 'ẛ',
|
||||
'Ạ' => 'Ạ',
|
||||
'ạ' => 'ạ',
|
||||
'Ả' => 'Ả',
|
||||
'ả' => 'ả',
|
||||
'Ấ' => 'Ấ',
|
||||
'ấ' => 'ấ',
|
||||
'Ầ' => 'Ầ',
|
||||
'ầ' => 'ầ',
|
||||
'Ẩ' => 'Ẩ',
|
||||
'ẩ' => 'ẩ',
|
||||
'Ẫ' => 'Ẫ',
|
||||
'ẫ' => 'ẫ',
|
||||
'Ậ' => 'Ậ',
|
||||
'ậ' => 'ậ',
|
||||
'Ắ' => 'Ắ',
|
||||
'ắ' => 'ắ',
|
||||
'Ằ' => 'Ằ',
|
||||
'ằ' => 'ằ',
|
||||
'Ẳ' => 'Ẳ',
|
||||
'ẳ' => 'ẳ',
|
||||
'Ẵ' => 'Ẵ',
|
||||
'ẵ' => 'ẵ',
|
||||
'Ặ' => 'Ặ',
|
||||
'ặ' => 'ặ',
|
||||
'Ẹ' => 'Ẹ',
|
||||
'ẹ' => 'ẹ',
|
||||
'Ẻ' => 'Ẻ',
|
||||
'ẻ' => 'ẻ',
|
||||
'Ẽ' => 'Ẽ',
|
||||
'ẽ' => 'ẽ',
|
||||
'Ế' => 'Ế',
|
||||
'ế' => 'ế',
|
||||
'Ề' => 'Ề',
|
||||
'ề' => 'ề',
|
||||
'Ể' => 'Ể',
|
||||
'ể' => 'ể',
|
||||
'Ễ' => 'Ễ',
|
||||
'ễ' => 'ễ',
|
||||
'Ệ' => 'Ệ',
|
||||
'ệ' => 'ệ',
|
||||
'Ỉ' => 'Ỉ',
|
||||
'ỉ' => 'ỉ',
|
||||
'Ị' => 'Ị',
|
||||
'ị' => 'ị',
|
||||
'Ọ' => 'Ọ',
|
||||
'ọ' => 'ọ',
|
||||
'Ỏ' => 'Ỏ',
|
||||
'ỏ' => 'ỏ',
|
||||
'Ố' => 'Ố',
|
||||
'ố' => 'ố',
|
||||
'Ồ' => 'Ồ',
|
||||
'ồ' => 'ồ',
|
||||
'Ổ' => 'Ổ',
|
||||
'ổ' => 'ổ',
|
||||
'Ỗ' => 'Ỗ',
|
||||
'ỗ' => 'ỗ',
|
||||
'Ộ' => 'Ộ',
|
||||
'ộ' => 'ộ',
|
||||
'Ớ' => 'Ớ',
|
||||
'ớ' => 'ớ',
|
||||
'Ờ' => 'Ờ',
|
||||
'ờ' => 'ờ',
|
||||
'Ở' => 'Ở',
|
||||
'ở' => 'ở',
|
||||
'Ỡ' => 'Ỡ',
|
||||
'ỡ' => 'ỡ',
|
||||
'Ợ' => 'Ợ',
|
||||
'ợ' => 'ợ',
|
||||
'Ụ' => 'Ụ',
|
||||
'ụ' => 'ụ',
|
||||
'Ủ' => 'Ủ',
|
||||
'ủ' => 'ủ',
|
||||
'Ứ' => 'Ứ',
|
||||
'ứ' => 'ứ',
|
||||
'Ừ' => 'Ừ',
|
||||
'ừ' => 'ừ',
|
||||
'Ử' => 'Ử',
|
||||
'ử' => 'ử',
|
||||
'Ữ' => 'Ữ',
|
||||
'ữ' => 'ữ',
|
||||
'Ự' => 'Ự',
|
||||
'ự' => 'ự',
|
||||
'Ỳ' => 'Ỳ',
|
||||
'ỳ' => 'ỳ',
|
||||
'Ỵ' => 'Ỵ',
|
||||
'ỵ' => 'ỵ',
|
||||
'Ỷ' => 'Ỷ',
|
||||
'ỷ' => 'ỷ',
|
||||
'Ỹ' => 'Ỹ',
|
||||
'ỹ' => 'ỹ',
|
||||
'ἀ' => 'ἀ',
|
||||
'ἁ' => 'ἁ',
|
||||
'ἂ' => 'ἂ',
|
||||
'ἃ' => 'ἃ',
|
||||
'ἄ' => 'ἄ',
|
||||
'ἅ' => 'ἅ',
|
||||
'ἆ' => 'ἆ',
|
||||
'ἇ' => 'ἇ',
|
||||
'Ἀ' => 'Ἀ',
|
||||
'Ἁ' => 'Ἁ',
|
||||
'Ἂ' => 'Ἂ',
|
||||
'Ἃ' => 'Ἃ',
|
||||
'Ἄ' => 'Ἄ',
|
||||
'Ἅ' => 'Ἅ',
|
||||
'Ἆ' => 'Ἆ',
|
||||
'Ἇ' => 'Ἇ',
|
||||
'ἐ' => 'ἐ',
|
||||
'ἑ' => 'ἑ',
|
||||
'ἒ' => 'ἒ',
|
||||
'ἓ' => 'ἓ',
|
||||
'ἔ' => 'ἔ',
|
||||
'ἕ' => 'ἕ',
|
||||
'Ἐ' => 'Ἐ',
|
||||
'Ἑ' => 'Ἑ',
|
||||
'Ἒ' => 'Ἒ',
|
||||
'Ἓ' => 'Ἓ',
|
||||
'Ἔ' => 'Ἔ',
|
||||
'Ἕ' => 'Ἕ',
|
||||
'ἠ' => 'ἠ',
|
||||
'ἡ' => 'ἡ',
|
||||
'ἢ' => 'ἢ',
|
||||
'ἣ' => 'ἣ',
|
||||
'ἤ' => 'ἤ',
|
||||
'ἥ' => 'ἥ',
|
||||
'ἦ' => 'ἦ',
|
||||
'ἧ' => 'ἧ',
|
||||
'Ἠ' => 'Ἠ',
|
||||
'Ἡ' => 'Ἡ',
|
||||
'Ἢ' => 'Ἢ',
|
||||
'Ἣ' => 'Ἣ',
|
||||
'Ἤ' => 'Ἤ',
|
||||
'Ἥ' => 'Ἥ',
|
||||
'Ἦ' => 'Ἦ',
|
||||
'Ἧ' => 'Ἧ',
|
||||
'ἰ' => 'ἰ',
|
||||
'ἱ' => 'ἱ',
|
||||
'ἲ' => 'ἲ',
|
||||
'ἳ' => 'ἳ',
|
||||
'ἴ' => 'ἴ',
|
||||
'ἵ' => 'ἵ',
|
||||
'ἶ' => 'ἶ',
|
||||
'ἷ' => 'ἷ',
|
||||
'Ἰ' => 'Ἰ',
|
||||
'Ἱ' => 'Ἱ',
|
||||
'Ἲ' => 'Ἲ',
|
||||
'Ἳ' => 'Ἳ',
|
||||
'Ἴ' => 'Ἴ',
|
||||
'Ἵ' => 'Ἵ',
|
||||
'Ἶ' => 'Ἶ',
|
||||
'Ἷ' => 'Ἷ',
|
||||
'ὀ' => 'ὀ',
|
||||
'ὁ' => 'ὁ',
|
||||
'ὂ' => 'ὂ',
|
||||
'ὃ' => 'ὃ',
|
||||
'ὄ' => 'ὄ',
|
||||
'ὅ' => 'ὅ',
|
||||
'Ὀ' => 'Ὀ',
|
||||
'Ὁ' => 'Ὁ',
|
||||
'Ὂ' => 'Ὂ',
|
||||
'Ὃ' => 'Ὃ',
|
||||
'Ὄ' => 'Ὄ',
|
||||
'Ὅ' => 'Ὅ',
|
||||
'ὐ' => 'ὐ',
|
||||
'ὑ' => 'ὑ',
|
||||
'ὒ' => 'ὒ',
|
||||
'ὓ' => 'ὓ',
|
||||
'ὔ' => 'ὔ',
|
||||
'ὕ' => 'ὕ',
|
||||
'ὖ' => 'ὖ',
|
||||
'ὗ' => 'ὗ',
|
||||
'Ὑ' => 'Ὑ',
|
||||
'Ὓ' => 'Ὓ',
|
||||
'Ὕ' => 'Ὕ',
|
||||
'Ὗ' => 'Ὗ',
|
||||
'ὠ' => 'ὠ',
|
||||
'ὡ' => 'ὡ',
|
||||
'ὢ' => 'ὢ',
|
||||
'ὣ' => 'ὣ',
|
||||
'ὤ' => 'ὤ',
|
||||
'ὥ' => 'ὥ',
|
||||
'ὦ' => 'ὦ',
|
||||
'ὧ' => 'ὧ',
|
||||
'Ὠ' => 'Ὠ',
|
||||
'Ὡ' => 'Ὡ',
|
||||
'Ὢ' => 'Ὢ',
|
||||
'Ὣ' => 'Ὣ',
|
||||
'Ὤ' => 'Ὤ',
|
||||
'Ὥ' => 'Ὥ',
|
||||
'Ὦ' => 'Ὦ',
|
||||
'Ὧ' => 'Ὧ',
|
||||
'ὰ' => 'ὰ',
|
||||
'ὲ' => 'ὲ',
|
||||
'ὴ' => 'ὴ',
|
||||
'ὶ' => 'ὶ',
|
||||
'ὸ' => 'ὸ',
|
||||
'ὺ' => 'ὺ',
|
||||
'ὼ' => 'ὼ',
|
||||
'ᾀ' => 'ᾀ',
|
||||
'ᾁ' => 'ᾁ',
|
||||
'ᾂ' => 'ᾂ',
|
||||
'ᾃ' => 'ᾃ',
|
||||
'ᾄ' => 'ᾄ',
|
||||
'ᾅ' => 'ᾅ',
|
||||
'ᾆ' => 'ᾆ',
|
||||
'ᾇ' => 'ᾇ',
|
||||
'ᾈ' => 'ᾈ',
|
||||
'ᾉ' => 'ᾉ',
|
||||
'ᾊ' => 'ᾊ',
|
||||
'ᾋ' => 'ᾋ',
|
||||
'ᾌ' => 'ᾌ',
|
||||
'ᾍ' => 'ᾍ',
|
||||
'ᾎ' => 'ᾎ',
|
||||
'ᾏ' => 'ᾏ',
|
||||
'ᾐ' => 'ᾐ',
|
||||
'ᾑ' => 'ᾑ',
|
||||
'ᾒ' => 'ᾒ',
|
||||
'ᾓ' => 'ᾓ',
|
||||
'ᾔ' => 'ᾔ',
|
||||
'ᾕ' => 'ᾕ',
|
||||
'ᾖ' => 'ᾖ',
|
||||
'ᾗ' => 'ᾗ',
|
||||
'ᾘ' => 'ᾘ',
|
||||
'ᾙ' => 'ᾙ',
|
||||
'ᾚ' => 'ᾚ',
|
||||
'ᾛ' => 'ᾛ',
|
||||
'ᾜ' => 'ᾜ',
|
||||
'ᾝ' => 'ᾝ',
|
||||
'ᾞ' => 'ᾞ',
|
||||
'ᾟ' => 'ᾟ',
|
||||
'ᾠ' => 'ᾠ',
|
||||
'ᾡ' => 'ᾡ',
|
||||
'ᾢ' => 'ᾢ',
|
||||
'ᾣ' => 'ᾣ',
|
||||
'ᾤ' => 'ᾤ',
|
||||
'ᾥ' => 'ᾥ',
|
||||
'ᾦ' => 'ᾦ',
|
||||
'ᾧ' => 'ᾧ',
|
||||
'ᾨ' => 'ᾨ',
|
||||
'ᾩ' => 'ᾩ',
|
||||
'ᾪ' => 'ᾪ',
|
||||
'ᾫ' => 'ᾫ',
|
||||
'ᾬ' => 'ᾬ',
|
||||
'ᾭ' => 'ᾭ',
|
||||
'ᾮ' => 'ᾮ',
|
||||
'ᾯ' => 'ᾯ',
|
||||
'ᾰ' => 'ᾰ',
|
||||
'ᾱ' => 'ᾱ',
|
||||
'ᾲ' => 'ᾲ',
|
||||
'ᾳ' => 'ᾳ',
|
||||
'ᾴ' => 'ᾴ',
|
||||
'ᾶ' => 'ᾶ',
|
||||
'ᾷ' => 'ᾷ',
|
||||
'Ᾰ' => 'Ᾰ',
|
||||
'Ᾱ' => 'Ᾱ',
|
||||
'Ὰ' => 'Ὰ',
|
||||
'ᾼ' => 'ᾼ',
|
||||
'῁' => '῁',
|
||||
'ῂ' => 'ῂ',
|
||||
'ῃ' => 'ῃ',
|
||||
'ῄ' => 'ῄ',
|
||||
'ῆ' => 'ῆ',
|
||||
'ῇ' => 'ῇ',
|
||||
'Ὲ' => 'Ὲ',
|
||||
'Ὴ' => 'Ὴ',
|
||||
'ῌ' => 'ῌ',
|
||||
'῍' => '῍',
|
||||
'῎' => '῎',
|
||||
'῏' => '῏',
|
||||
'ῐ' => 'ῐ',
|
||||
'ῑ' => 'ῑ',
|
||||
'ῒ' => 'ῒ',
|
||||
'ῖ' => 'ῖ',
|
||||
'ῗ' => 'ῗ',
|
||||
'Ῐ' => 'Ῐ',
|
||||
'Ῑ' => 'Ῑ',
|
||||
'Ὶ' => 'Ὶ',
|
||||
'῝' => '῝',
|
||||
'῞' => '῞',
|
||||
'῟' => '῟',
|
||||
'ῠ' => 'ῠ',
|
||||
'ῡ' => 'ῡ',
|
||||
'ῢ' => 'ῢ',
|
||||
'ῤ' => 'ῤ',
|
||||
'ῥ' => 'ῥ',
|
||||
'ῦ' => 'ῦ',
|
||||
'ῧ' => 'ῧ',
|
||||
'Ῠ' => 'Ῠ',
|
||||
'Ῡ' => 'Ῡ',
|
||||
'Ὺ' => 'Ὺ',
|
||||
'Ῥ' => 'Ῥ',
|
||||
'῭' => '῭',
|
||||
'ῲ' => 'ῲ',
|
||||
'ῳ' => 'ῳ',
|
||||
'ῴ' => 'ῴ',
|
||||
'ῶ' => 'ῶ',
|
||||
'ῷ' => 'ῷ',
|
||||
'Ὸ' => 'Ὸ',
|
||||
'Ὼ' => 'Ὼ',
|
||||
'ῼ' => 'ῼ',
|
||||
'↚' => '↚',
|
||||
'↛' => '↛',
|
||||
'↮' => '↮',
|
||||
'⇍' => '⇍',
|
||||
'⇎' => '⇎',
|
||||
'⇏' => '⇏',
|
||||
'∄' => '∄',
|
||||
'∉' => '∉',
|
||||
'∌' => '∌',
|
||||
'∤' => '∤',
|
||||
'∦' => '∦',
|
||||
'≁' => '≁',
|
||||
'≄' => '≄',
|
||||
'≇' => '≇',
|
||||
'≉' => '≉',
|
||||
'≠' => '≠',
|
||||
'≢' => '≢',
|
||||
'≭' => '≭',
|
||||
'≮' => '≮',
|
||||
'≯' => '≯',
|
||||
'≰' => '≰',
|
||||
'≱' => '≱',
|
||||
'≴' => '≴',
|
||||
'≵' => '≵',
|
||||
'≸' => '≸',
|
||||
'≹' => '≹',
|
||||
'⊀' => '⊀',
|
||||
'⊁' => '⊁',
|
||||
'⊄' => '⊄',
|
||||
'⊅' => '⊅',
|
||||
'⊈' => '⊈',
|
||||
'⊉' => '⊉',
|
||||
'⊬' => '⊬',
|
||||
'⊭' => '⊭',
|
||||
'⊮' => '⊮',
|
||||
'⊯' => '⊯',
|
||||
'⋠' => '⋠',
|
||||
'⋡' => '⋡',
|
||||
'⋢' => '⋢',
|
||||
'⋣' => '⋣',
|
||||
'⋪' => '⋪',
|
||||
'⋫' => '⋫',
|
||||
'⋬' => '⋬',
|
||||
'⋭' => '⋭',
|
||||
'が' => 'が',
|
||||
'ぎ' => 'ぎ',
|
||||
'ぐ' => 'ぐ',
|
||||
'げ' => 'げ',
|
||||
'ご' => 'ご',
|
||||
'ざ' => 'ざ',
|
||||
'じ' => 'じ',
|
||||
'ず' => 'ず',
|
||||
'ぜ' => 'ぜ',
|
||||
'ぞ' => 'ぞ',
|
||||
'だ' => 'だ',
|
||||
'ぢ' => 'ぢ',
|
||||
'づ' => 'づ',
|
||||
'で' => 'で',
|
||||
'ど' => 'ど',
|
||||
'ば' => 'ば',
|
||||
'ぱ' => 'ぱ',
|
||||
'び' => 'び',
|
||||
'ぴ' => 'ぴ',
|
||||
'ぶ' => 'ぶ',
|
||||
'ぷ' => 'ぷ',
|
||||
'べ' => 'べ',
|
||||
'ぺ' => 'ぺ',
|
||||
'ぼ' => 'ぼ',
|
||||
'ぽ' => 'ぽ',
|
||||
'ゔ' => 'ゔ',
|
||||
'ゞ' => 'ゞ',
|
||||
'ガ' => 'ガ',
|
||||
'ギ' => 'ギ',
|
||||
'グ' => 'グ',
|
||||
'ゲ' => 'ゲ',
|
||||
'ゴ' => 'ゴ',
|
||||
'ザ' => 'ザ',
|
||||
'ジ' => 'ジ',
|
||||
'ズ' => 'ズ',
|
||||
'ゼ' => 'ゼ',
|
||||
'ゾ' => 'ゾ',
|
||||
'ダ' => 'ダ',
|
||||
'ヂ' => 'ヂ',
|
||||
'ヅ' => 'ヅ',
|
||||
'デ' => 'デ',
|
||||
'ド' => 'ド',
|
||||
'バ' => 'バ',
|
||||
'パ' => 'パ',
|
||||
'ビ' => 'ビ',
|
||||
'ピ' => 'ピ',
|
||||
'ブ' => 'ブ',
|
||||
'プ' => 'プ',
|
||||
'ベ' => 'ベ',
|
||||
'ペ' => 'ペ',
|
||||
'ボ' => 'ボ',
|
||||
'ポ' => 'ポ',
|
||||
'ヴ' => 'ヴ',
|
||||
'ヷ' => 'ヷ',
|
||||
'ヸ' => 'ヸ',
|
||||
'ヹ' => 'ヹ',
|
||||
'ヺ' => 'ヺ',
|
||||
'ヾ' => 'ヾ',
|
||||
'𑂚' => '𑂚',
|
||||
'𑂜' => '𑂜',
|
||||
'𑂫' => '𑂫',
|
||||
'𑄮' => '𑄮',
|
||||
'𑄯' => '𑄯',
|
||||
'𑍋' => '𑍋',
|
||||
'𑍌' => '𑍌',
|
||||
'𑒻' => '𑒻',
|
||||
'𑒼' => '𑒼',
|
||||
'𑒾' => '𑒾',
|
||||
'𑖺' => '𑖺',
|
||||
'𑖻' => '𑖻',
|
||||
'𑤸' => '𑤸',
|
||||
);
|
||||
+2065
File diff suppressed because it is too large
Load Diff
+876
@@ -0,0 +1,876 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'̀' => 230,
|
||||
'́' => 230,
|
||||
'̂' => 230,
|
||||
'̃' => 230,
|
||||
'̄' => 230,
|
||||
'̅' => 230,
|
||||
'̆' => 230,
|
||||
'̇' => 230,
|
||||
'̈' => 230,
|
||||
'̉' => 230,
|
||||
'̊' => 230,
|
||||
'̋' => 230,
|
||||
'̌' => 230,
|
||||
'̍' => 230,
|
||||
'̎' => 230,
|
||||
'̏' => 230,
|
||||
'̐' => 230,
|
||||
'̑' => 230,
|
||||
'̒' => 230,
|
||||
'̓' => 230,
|
||||
'̔' => 230,
|
||||
'̕' => 232,
|
||||
'̖' => 220,
|
||||
'̗' => 220,
|
||||
'̘' => 220,
|
||||
'̙' => 220,
|
||||
'̚' => 232,
|
||||
'̛' => 216,
|
||||
'̜' => 220,
|
||||
'̝' => 220,
|
||||
'̞' => 220,
|
||||
'̟' => 220,
|
||||
'̠' => 220,
|
||||
'̡' => 202,
|
||||
'̢' => 202,
|
||||
'̣' => 220,
|
||||
'̤' => 220,
|
||||
'̥' => 220,
|
||||
'̦' => 220,
|
||||
'̧' => 202,
|
||||
'̨' => 202,
|
||||
'̩' => 220,
|
||||
'̪' => 220,
|
||||
'̫' => 220,
|
||||
'̬' => 220,
|
||||
'̭' => 220,
|
||||
'̮' => 220,
|
||||
'̯' => 220,
|
||||
'̰' => 220,
|
||||
'̱' => 220,
|
||||
'̲' => 220,
|
||||
'̳' => 220,
|
||||
'̴' => 1,
|
||||
'̵' => 1,
|
||||
'̶' => 1,
|
||||
'̷' => 1,
|
||||
'̸' => 1,
|
||||
'̹' => 220,
|
||||
'̺' => 220,
|
||||
'̻' => 220,
|
||||
'̼' => 220,
|
||||
'̽' => 230,
|
||||
'̾' => 230,
|
||||
'̿' => 230,
|
||||
'̀' => 230,
|
||||
'́' => 230,
|
||||
'͂' => 230,
|
||||
'̓' => 230,
|
||||
'̈́' => 230,
|
||||
'ͅ' => 240,
|
||||
'͆' => 230,
|
||||
'͇' => 220,
|
||||
'͈' => 220,
|
||||
'͉' => 220,
|
||||
'͊' => 230,
|
||||
'͋' => 230,
|
||||
'͌' => 230,
|
||||
'͍' => 220,
|
||||
'͎' => 220,
|
||||
'͐' => 230,
|
||||
'͑' => 230,
|
||||
'͒' => 230,
|
||||
'͓' => 220,
|
||||
'͔' => 220,
|
||||
'͕' => 220,
|
||||
'͖' => 220,
|
||||
'͗' => 230,
|
||||
'͘' => 232,
|
||||
'͙' => 220,
|
||||
'͚' => 220,
|
||||
'͛' => 230,
|
||||
'͜' => 233,
|
||||
'͝' => 234,
|
||||
'͞' => 234,
|
||||
'͟' => 233,
|
||||
'͠' => 234,
|
||||
'͡' => 234,
|
||||
'͢' => 233,
|
||||
'ͣ' => 230,
|
||||
'ͤ' => 230,
|
||||
'ͥ' => 230,
|
||||
'ͦ' => 230,
|
||||
'ͧ' => 230,
|
||||
'ͨ' => 230,
|
||||
'ͩ' => 230,
|
||||
'ͪ' => 230,
|
||||
'ͫ' => 230,
|
||||
'ͬ' => 230,
|
||||
'ͭ' => 230,
|
||||
'ͮ' => 230,
|
||||
'ͯ' => 230,
|
||||
'҃' => 230,
|
||||
'҄' => 230,
|
||||
'҅' => 230,
|
||||
'҆' => 230,
|
||||
'҇' => 230,
|
||||
'֑' => 220,
|
||||
'֒' => 230,
|
||||
'֓' => 230,
|
||||
'֔' => 230,
|
||||
'֕' => 230,
|
||||
'֖' => 220,
|
||||
'֗' => 230,
|
||||
'֘' => 230,
|
||||
'֙' => 230,
|
||||
'֚' => 222,
|
||||
'֛' => 220,
|
||||
'֜' => 230,
|
||||
'֝' => 230,
|
||||
'֞' => 230,
|
||||
'֟' => 230,
|
||||
'֠' => 230,
|
||||
'֡' => 230,
|
||||
'֢' => 220,
|
||||
'֣' => 220,
|
||||
'֤' => 220,
|
||||
'֥' => 220,
|
||||
'֦' => 220,
|
||||
'֧' => 220,
|
||||
'֨' => 230,
|
||||
'֩' => 230,
|
||||
'֪' => 220,
|
||||
'֫' => 230,
|
||||
'֬' => 230,
|
||||
'֭' => 222,
|
||||
'֮' => 228,
|
||||
'֯' => 230,
|
||||
'ְ' => 10,
|
||||
'ֱ' => 11,
|
||||
'ֲ' => 12,
|
||||
'ֳ' => 13,
|
||||
'ִ' => 14,
|
||||
'ֵ' => 15,
|
||||
'ֶ' => 16,
|
||||
'ַ' => 17,
|
||||
'ָ' => 18,
|
||||
'ֹ' => 19,
|
||||
'ֺ' => 19,
|
||||
'ֻ' => 20,
|
||||
'ּ' => 21,
|
||||
'ֽ' => 22,
|
||||
'ֿ' => 23,
|
||||
'ׁ' => 24,
|
||||
'ׂ' => 25,
|
||||
'ׄ' => 230,
|
||||
'ׅ' => 220,
|
||||
'ׇ' => 18,
|
||||
'ؐ' => 230,
|
||||
'ؑ' => 230,
|
||||
'ؒ' => 230,
|
||||
'ؓ' => 230,
|
||||
'ؔ' => 230,
|
||||
'ؕ' => 230,
|
||||
'ؖ' => 230,
|
||||
'ؗ' => 230,
|
||||
'ؘ' => 30,
|
||||
'ؙ' => 31,
|
||||
'ؚ' => 32,
|
||||
'ً' => 27,
|
||||
'ٌ' => 28,
|
||||
'ٍ' => 29,
|
||||
'َ' => 30,
|
||||
'ُ' => 31,
|
||||
'ِ' => 32,
|
||||
'ّ' => 33,
|
||||
'ْ' => 34,
|
||||
'ٓ' => 230,
|
||||
'ٔ' => 230,
|
||||
'ٕ' => 220,
|
||||
'ٖ' => 220,
|
||||
'ٗ' => 230,
|
||||
'٘' => 230,
|
||||
'ٙ' => 230,
|
||||
'ٚ' => 230,
|
||||
'ٛ' => 230,
|
||||
'ٜ' => 220,
|
||||
'ٝ' => 230,
|
||||
'ٞ' => 230,
|
||||
'ٟ' => 220,
|
||||
'ٰ' => 35,
|
||||
'ۖ' => 230,
|
||||
'ۗ' => 230,
|
||||
'ۘ' => 230,
|
||||
'ۙ' => 230,
|
||||
'ۚ' => 230,
|
||||
'ۛ' => 230,
|
||||
'ۜ' => 230,
|
||||
'۟' => 230,
|
||||
'۠' => 230,
|
||||
'ۡ' => 230,
|
||||
'ۢ' => 230,
|
||||
'ۣ' => 220,
|
||||
'ۤ' => 230,
|
||||
'ۧ' => 230,
|
||||
'ۨ' => 230,
|
||||
'۪' => 220,
|
||||
'۫' => 230,
|
||||
'۬' => 230,
|
||||
'ۭ' => 220,
|
||||
'ܑ' => 36,
|
||||
'ܰ' => 230,
|
||||
'ܱ' => 220,
|
||||
'ܲ' => 230,
|
||||
'ܳ' => 230,
|
||||
'ܴ' => 220,
|
||||
'ܵ' => 230,
|
||||
'ܶ' => 230,
|
||||
'ܷ' => 220,
|
||||
'ܸ' => 220,
|
||||
'ܹ' => 220,
|
||||
'ܺ' => 230,
|
||||
'ܻ' => 220,
|
||||
'ܼ' => 220,
|
||||
'ܽ' => 230,
|
||||
'ܾ' => 220,
|
||||
'ܿ' => 230,
|
||||
'݀' => 230,
|
||||
'݁' => 230,
|
||||
'݂' => 220,
|
||||
'݃' => 230,
|
||||
'݄' => 220,
|
||||
'݅' => 230,
|
||||
'݆' => 220,
|
||||
'݇' => 230,
|
||||
'݈' => 220,
|
||||
'݉' => 230,
|
||||
'݊' => 230,
|
||||
'߫' => 230,
|
||||
'߬' => 230,
|
||||
'߭' => 230,
|
||||
'߮' => 230,
|
||||
'߯' => 230,
|
||||
'߰' => 230,
|
||||
'߱' => 230,
|
||||
'߲' => 220,
|
||||
'߳' => 230,
|
||||
'߽' => 220,
|
||||
'ࠖ' => 230,
|
||||
'ࠗ' => 230,
|
||||
'࠘' => 230,
|
||||
'࠙' => 230,
|
||||
'ࠛ' => 230,
|
||||
'ࠜ' => 230,
|
||||
'ࠝ' => 230,
|
||||
'ࠞ' => 230,
|
||||
'ࠟ' => 230,
|
||||
'ࠠ' => 230,
|
||||
'ࠡ' => 230,
|
||||
'ࠢ' => 230,
|
||||
'ࠣ' => 230,
|
||||
'ࠥ' => 230,
|
||||
'ࠦ' => 230,
|
||||
'ࠧ' => 230,
|
||||
'ࠩ' => 230,
|
||||
'ࠪ' => 230,
|
||||
'ࠫ' => 230,
|
||||
'ࠬ' => 230,
|
||||
'࠭' => 230,
|
||||
'࡙' => 220,
|
||||
'࡚' => 220,
|
||||
'࡛' => 220,
|
||||
'࣓' => 220,
|
||||
'ࣔ' => 230,
|
||||
'ࣕ' => 230,
|
||||
'ࣖ' => 230,
|
||||
'ࣗ' => 230,
|
||||
'ࣘ' => 230,
|
||||
'ࣙ' => 230,
|
||||
'ࣚ' => 230,
|
||||
'ࣛ' => 230,
|
||||
'ࣜ' => 230,
|
||||
'ࣝ' => 230,
|
||||
'ࣞ' => 230,
|
||||
'ࣟ' => 230,
|
||||
'࣠' => 230,
|
||||
'࣡' => 230,
|
||||
'ࣣ' => 220,
|
||||
'ࣤ' => 230,
|
||||
'ࣥ' => 230,
|
||||
'ࣦ' => 220,
|
||||
'ࣧ' => 230,
|
||||
'ࣨ' => 230,
|
||||
'ࣩ' => 220,
|
||||
'࣪' => 230,
|
||||
'࣫' => 230,
|
||||
'࣬' => 230,
|
||||
'࣭' => 220,
|
||||
'࣮' => 220,
|
||||
'࣯' => 220,
|
||||
'ࣰ' => 27,
|
||||
'ࣱ' => 28,
|
||||
'ࣲ' => 29,
|
||||
'ࣳ' => 230,
|
||||
'ࣴ' => 230,
|
||||
'ࣵ' => 230,
|
||||
'ࣶ' => 220,
|
||||
'ࣷ' => 230,
|
||||
'ࣸ' => 230,
|
||||
'ࣹ' => 220,
|
||||
'ࣺ' => 220,
|
||||
'ࣻ' => 230,
|
||||
'ࣼ' => 230,
|
||||
'ࣽ' => 230,
|
||||
'ࣾ' => 230,
|
||||
'ࣿ' => 230,
|
||||
'़' => 7,
|
||||
'्' => 9,
|
||||
'॑' => 230,
|
||||
'॒' => 220,
|
||||
'॓' => 230,
|
||||
'॔' => 230,
|
||||
'়' => 7,
|
||||
'্' => 9,
|
||||
'৾' => 230,
|
||||
'਼' => 7,
|
||||
'੍' => 9,
|
||||
'઼' => 7,
|
||||
'્' => 9,
|
||||
'଼' => 7,
|
||||
'୍' => 9,
|
||||
'்' => 9,
|
||||
'్' => 9,
|
||||
'ౕ' => 84,
|
||||
'ౖ' => 91,
|
||||
'಼' => 7,
|
||||
'್' => 9,
|
||||
'഻' => 9,
|
||||
'഼' => 9,
|
||||
'്' => 9,
|
||||
'්' => 9,
|
||||
'ุ' => 103,
|
||||
'ู' => 103,
|
||||
'ฺ' => 9,
|
||||
'่' => 107,
|
||||
'้' => 107,
|
||||
'๊' => 107,
|
||||
'๋' => 107,
|
||||
'ຸ' => 118,
|
||||
'ູ' => 118,
|
||||
'຺' => 9,
|
||||
'່' => 122,
|
||||
'້' => 122,
|
||||
'໊' => 122,
|
||||
'໋' => 122,
|
||||
'༘' => 220,
|
||||
'༙' => 220,
|
||||
'༵' => 220,
|
||||
'༷' => 220,
|
||||
'༹' => 216,
|
||||
'ཱ' => 129,
|
||||
'ི' => 130,
|
||||
'ུ' => 132,
|
||||
'ེ' => 130,
|
||||
'ཻ' => 130,
|
||||
'ོ' => 130,
|
||||
'ཽ' => 130,
|
||||
'ྀ' => 130,
|
||||
'ྂ' => 230,
|
||||
'ྃ' => 230,
|
||||
'྄' => 9,
|
||||
'྆' => 230,
|
||||
'྇' => 230,
|
||||
'࿆' => 220,
|
||||
'့' => 7,
|
||||
'္' => 9,
|
||||
'်' => 9,
|
||||
'ႍ' => 220,
|
||||
'፝' => 230,
|
||||
'፞' => 230,
|
||||
'፟' => 230,
|
||||
'᜔' => 9,
|
||||
'᜴' => 9,
|
||||
'្' => 9,
|
||||
'៝' => 230,
|
||||
'ᢩ' => 228,
|
||||
'᤹' => 222,
|
||||
'᤺' => 230,
|
||||
'᤻' => 220,
|
||||
'ᨗ' => 230,
|
||||
'ᨘ' => 220,
|
||||
'᩠' => 9,
|
||||
'᩵' => 230,
|
||||
'᩶' => 230,
|
||||
'᩷' => 230,
|
||||
'᩸' => 230,
|
||||
'᩹' => 230,
|
||||
'᩺' => 230,
|
||||
'᩻' => 230,
|
||||
'᩼' => 230,
|
||||
'᩿' => 220,
|
||||
'᪰' => 230,
|
||||
'᪱' => 230,
|
||||
'᪲' => 230,
|
||||
'᪳' => 230,
|
||||
'᪴' => 230,
|
||||
'᪵' => 220,
|
||||
'᪶' => 220,
|
||||
'᪷' => 220,
|
||||
'᪸' => 220,
|
||||
'᪹' => 220,
|
||||
'᪺' => 220,
|
||||
'᪻' => 230,
|
||||
'᪼' => 230,
|
||||
'᪽' => 220,
|
||||
'ᪿ' => 220,
|
||||
'ᫀ' => 220,
|
||||
'᬴' => 7,
|
||||
'᭄' => 9,
|
||||
'᭫' => 230,
|
||||
'᭬' => 220,
|
||||
'᭭' => 230,
|
||||
'᭮' => 230,
|
||||
'᭯' => 230,
|
||||
'᭰' => 230,
|
||||
'᭱' => 230,
|
||||
'᭲' => 230,
|
||||
'᭳' => 230,
|
||||
'᮪' => 9,
|
||||
'᮫' => 9,
|
||||
'᯦' => 7,
|
||||
'᯲' => 9,
|
||||
'᯳' => 9,
|
||||
'᰷' => 7,
|
||||
'᳐' => 230,
|
||||
'᳑' => 230,
|
||||
'᳒' => 230,
|
||||
'᳔' => 1,
|
||||
'᳕' => 220,
|
||||
'᳖' => 220,
|
||||
'᳗' => 220,
|
||||
'᳘' => 220,
|
||||
'᳙' => 220,
|
||||
'᳚' => 230,
|
||||
'᳛' => 230,
|
||||
'᳜' => 220,
|
||||
'᳝' => 220,
|
||||
'᳞' => 220,
|
||||
'᳟' => 220,
|
||||
'᳠' => 230,
|
||||
'᳢' => 1,
|
||||
'᳣' => 1,
|
||||
'᳤' => 1,
|
||||
'᳥' => 1,
|
||||
'᳦' => 1,
|
||||
'᳧' => 1,
|
||||
'᳨' => 1,
|
||||
'᳭' => 220,
|
||||
'᳴' => 230,
|
||||
'᳸' => 230,
|
||||
'᳹' => 230,
|
||||
'᷀' => 230,
|
||||
'᷁' => 230,
|
||||
'᷂' => 220,
|
||||
'᷃' => 230,
|
||||
'᷄' => 230,
|
||||
'᷅' => 230,
|
||||
'᷆' => 230,
|
||||
'᷇' => 230,
|
||||
'᷈' => 230,
|
||||
'᷉' => 230,
|
||||
'᷊' => 220,
|
||||
'᷋' => 230,
|
||||
'᷌' => 230,
|
||||
'᷍' => 234,
|
||||
'᷎' => 214,
|
||||
'᷏' => 220,
|
||||
'᷐' => 202,
|
||||
'᷑' => 230,
|
||||
'᷒' => 230,
|
||||
'ᷓ' => 230,
|
||||
'ᷔ' => 230,
|
||||
'ᷕ' => 230,
|
||||
'ᷖ' => 230,
|
||||
'ᷗ' => 230,
|
||||
'ᷘ' => 230,
|
||||
'ᷙ' => 230,
|
||||
'ᷚ' => 230,
|
||||
'ᷛ' => 230,
|
||||
'ᷜ' => 230,
|
||||
'ᷝ' => 230,
|
||||
'ᷞ' => 230,
|
||||
'ᷟ' => 230,
|
||||
'ᷠ' => 230,
|
||||
'ᷡ' => 230,
|
||||
'ᷢ' => 230,
|
||||
'ᷣ' => 230,
|
||||
'ᷤ' => 230,
|
||||
'ᷥ' => 230,
|
||||
'ᷦ' => 230,
|
||||
'ᷧ' => 230,
|
||||
'ᷨ' => 230,
|
||||
'ᷩ' => 230,
|
||||
'ᷪ' => 230,
|
||||
'ᷫ' => 230,
|
||||
'ᷬ' => 230,
|
||||
'ᷭ' => 230,
|
||||
'ᷮ' => 230,
|
||||
'ᷯ' => 230,
|
||||
'ᷰ' => 230,
|
||||
'ᷱ' => 230,
|
||||
'ᷲ' => 230,
|
||||
'ᷳ' => 230,
|
||||
'ᷴ' => 230,
|
||||
'᷵' => 230,
|
||||
'᷶' => 232,
|
||||
'᷷' => 228,
|
||||
'᷸' => 228,
|
||||
'᷹' => 220,
|
||||
'᷻' => 230,
|
||||
'᷼' => 233,
|
||||
'᷽' => 220,
|
||||
'᷾' => 230,
|
||||
'᷿' => 220,
|
||||
'⃐' => 230,
|
||||
'⃑' => 230,
|
||||
'⃒' => 1,
|
||||
'⃓' => 1,
|
||||
'⃔' => 230,
|
||||
'⃕' => 230,
|
||||
'⃖' => 230,
|
||||
'⃗' => 230,
|
||||
'⃘' => 1,
|
||||
'⃙' => 1,
|
||||
'⃚' => 1,
|
||||
'⃛' => 230,
|
||||
'⃜' => 230,
|
||||
'⃡' => 230,
|
||||
'⃥' => 1,
|
||||
'⃦' => 1,
|
||||
'⃧' => 230,
|
||||
'⃨' => 220,
|
||||
'⃩' => 230,
|
||||
'⃪' => 1,
|
||||
'⃫' => 1,
|
||||
'⃬' => 220,
|
||||
'⃭' => 220,
|
||||
'⃮' => 220,
|
||||
'⃯' => 220,
|
||||
'⃰' => 230,
|
||||
'⳯' => 230,
|
||||
'⳰' => 230,
|
||||
'⳱' => 230,
|
||||
'⵿' => 9,
|
||||
'ⷠ' => 230,
|
||||
'ⷡ' => 230,
|
||||
'ⷢ' => 230,
|
||||
'ⷣ' => 230,
|
||||
'ⷤ' => 230,
|
||||
'ⷥ' => 230,
|
||||
'ⷦ' => 230,
|
||||
'ⷧ' => 230,
|
||||
'ⷨ' => 230,
|
||||
'ⷩ' => 230,
|
||||
'ⷪ' => 230,
|
||||
'ⷫ' => 230,
|
||||
'ⷬ' => 230,
|
||||
'ⷭ' => 230,
|
||||
'ⷮ' => 230,
|
||||
'ⷯ' => 230,
|
||||
'ⷰ' => 230,
|
||||
'ⷱ' => 230,
|
||||
'ⷲ' => 230,
|
||||
'ⷳ' => 230,
|
||||
'ⷴ' => 230,
|
||||
'ⷵ' => 230,
|
||||
'ⷶ' => 230,
|
||||
'ⷷ' => 230,
|
||||
'ⷸ' => 230,
|
||||
'ⷹ' => 230,
|
||||
'ⷺ' => 230,
|
||||
'ⷻ' => 230,
|
||||
'ⷼ' => 230,
|
||||
'ⷽ' => 230,
|
||||
'ⷾ' => 230,
|
||||
'ⷿ' => 230,
|
||||
'〪' => 218,
|
||||
'〫' => 228,
|
||||
'〬' => 232,
|
||||
'〭' => 222,
|
||||
'〮' => 224,
|
||||
'〯' => 224,
|
||||
'゙' => 8,
|
||||
'゚' => 8,
|
||||
'꙯' => 230,
|
||||
'ꙴ' => 230,
|
||||
'ꙵ' => 230,
|
||||
'ꙶ' => 230,
|
||||
'ꙷ' => 230,
|
||||
'ꙸ' => 230,
|
||||
'ꙹ' => 230,
|
||||
'ꙺ' => 230,
|
||||
'ꙻ' => 230,
|
||||
'꙼' => 230,
|
||||
'꙽' => 230,
|
||||
'ꚞ' => 230,
|
||||
'ꚟ' => 230,
|
||||
'꛰' => 230,
|
||||
'꛱' => 230,
|
||||
'꠆' => 9,
|
||||
'꠬' => 9,
|
||||
'꣄' => 9,
|
||||
'꣠' => 230,
|
||||
'꣡' => 230,
|
||||
'꣢' => 230,
|
||||
'꣣' => 230,
|
||||
'꣤' => 230,
|
||||
'꣥' => 230,
|
||||
'꣦' => 230,
|
||||
'꣧' => 230,
|
||||
'꣨' => 230,
|
||||
'꣩' => 230,
|
||||
'꣪' => 230,
|
||||
'꣫' => 230,
|
||||
'꣬' => 230,
|
||||
'꣭' => 230,
|
||||
'꣮' => 230,
|
||||
'꣯' => 230,
|
||||
'꣰' => 230,
|
||||
'꣱' => 230,
|
||||
'꤫' => 220,
|
||||
'꤬' => 220,
|
||||
'꤭' => 220,
|
||||
'꥓' => 9,
|
||||
'꦳' => 7,
|
||||
'꧀' => 9,
|
||||
'ꪰ' => 230,
|
||||
'ꪲ' => 230,
|
||||
'ꪳ' => 230,
|
||||
'ꪴ' => 220,
|
||||
'ꪷ' => 230,
|
||||
'ꪸ' => 230,
|
||||
'ꪾ' => 230,
|
||||
'꪿' => 230,
|
||||
'꫁' => 230,
|
||||
'꫶' => 9,
|
||||
'꯭' => 9,
|
||||
'ﬞ' => 26,
|
||||
'︠' => 230,
|
||||
'︡' => 230,
|
||||
'︢' => 230,
|
||||
'︣' => 230,
|
||||
'︤' => 230,
|
||||
'︥' => 230,
|
||||
'︦' => 230,
|
||||
'︧' => 220,
|
||||
'︨' => 220,
|
||||
'︩' => 220,
|
||||
'︪' => 220,
|
||||
'︫' => 220,
|
||||
'︬' => 220,
|
||||
'︭' => 220,
|
||||
'︮' => 230,
|
||||
'︯' => 230,
|
||||
'𐇽' => 220,
|
||||
'𐋠' => 220,
|
||||
'𐍶' => 230,
|
||||
'𐍷' => 230,
|
||||
'𐍸' => 230,
|
||||
'𐍹' => 230,
|
||||
'𐍺' => 230,
|
||||
'𐨍' => 220,
|
||||
'𐨏' => 230,
|
||||
'𐨸' => 230,
|
||||
'𐨹' => 1,
|
||||
'𐨺' => 220,
|
||||
'𐨿' => 9,
|
||||
'𐫥' => 230,
|
||||
'𐫦' => 220,
|
||||
'𐴤' => 230,
|
||||
'𐴥' => 230,
|
||||
'𐴦' => 230,
|
||||
'𐴧' => 230,
|
||||
'𐺫' => 230,
|
||||
'𐺬' => 230,
|
||||
'𐽆' => 220,
|
||||
'𐽇' => 220,
|
||||
'𐽈' => 230,
|
||||
'𐽉' => 230,
|
||||
'𐽊' => 230,
|
||||
'𐽋' => 220,
|
||||
'𐽌' => 230,
|
||||
'𐽍' => 220,
|
||||
'𐽎' => 220,
|
||||
'𐽏' => 220,
|
||||
'𐽐' => 220,
|
||||
'𑁆' => 9,
|
||||
'𑁿' => 9,
|
||||
'𑂹' => 9,
|
||||
'𑂺' => 7,
|
||||
'𑄀' => 230,
|
||||
'𑄁' => 230,
|
||||
'𑄂' => 230,
|
||||
'𑄳' => 9,
|
||||
'𑄴' => 9,
|
||||
'𑅳' => 7,
|
||||
'𑇀' => 9,
|
||||
'𑇊' => 7,
|
||||
'𑈵' => 9,
|
||||
'𑈶' => 7,
|
||||
'𑋩' => 7,
|
||||
'𑋪' => 9,
|
||||
'𑌻' => 7,
|
||||
'𑌼' => 7,
|
||||
'𑍍' => 9,
|
||||
'𑍦' => 230,
|
||||
'𑍧' => 230,
|
||||
'𑍨' => 230,
|
||||
'𑍩' => 230,
|
||||
'𑍪' => 230,
|
||||
'𑍫' => 230,
|
||||
'𑍬' => 230,
|
||||
'𑍰' => 230,
|
||||
'𑍱' => 230,
|
||||
'𑍲' => 230,
|
||||
'𑍳' => 230,
|
||||
'𑍴' => 230,
|
||||
'𑑂' => 9,
|
||||
'𑑆' => 7,
|
||||
'𑑞' => 230,
|
||||
'𑓂' => 9,
|
||||
'𑓃' => 7,
|
||||
'𑖿' => 9,
|
||||
'𑗀' => 7,
|
||||
'𑘿' => 9,
|
||||
'𑚶' => 9,
|
||||
'𑚷' => 7,
|
||||
'𑜫' => 9,
|
||||
'𑠹' => 9,
|
||||
'𑠺' => 7,
|
||||
'𑤽' => 9,
|
||||
'𑤾' => 9,
|
||||
'𑥃' => 7,
|
||||
'𑧠' => 9,
|
||||
'𑨴' => 9,
|
||||
'𑩇' => 9,
|
||||
'𑪙' => 9,
|
||||
'𑰿' => 9,
|
||||
'𑵂' => 7,
|
||||
'𑵄' => 9,
|
||||
'𑵅' => 9,
|
||||
'𑶗' => 9,
|
||||
'𖫰' => 1,
|
||||
'𖫱' => 1,
|
||||
'𖫲' => 1,
|
||||
'𖫳' => 1,
|
||||
'𖫴' => 1,
|
||||
'𖬰' => 230,
|
||||
'𖬱' => 230,
|
||||
'𖬲' => 230,
|
||||
'𖬳' => 230,
|
||||
'𖬴' => 230,
|
||||
'𖬵' => 230,
|
||||
'𖬶' => 230,
|
||||
'𖿰' => 6,
|
||||
'𖿱' => 6,
|
||||
'𛲞' => 1,
|
||||
'𝅥' => 216,
|
||||
'𝅦' => 216,
|
||||
'𝅧' => 1,
|
||||
'𝅨' => 1,
|
||||
'𝅩' => 1,
|
||||
'𝅭' => 226,
|
||||
'𝅮' => 216,
|
||||
'𝅯' => 216,
|
||||
'𝅰' => 216,
|
||||
'𝅱' => 216,
|
||||
'𝅲' => 216,
|
||||
'𝅻' => 220,
|
||||
'𝅼' => 220,
|
||||
'𝅽' => 220,
|
||||
'𝅾' => 220,
|
||||
'𝅿' => 220,
|
||||
'𝆀' => 220,
|
||||
'𝆁' => 220,
|
||||
'𝆂' => 220,
|
||||
'𝆅' => 230,
|
||||
'𝆆' => 230,
|
||||
'𝆇' => 230,
|
||||
'𝆈' => 230,
|
||||
'𝆉' => 230,
|
||||
'𝆊' => 220,
|
||||
'𝆋' => 220,
|
||||
'𝆪' => 230,
|
||||
'𝆫' => 230,
|
||||
'𝆬' => 230,
|
||||
'𝆭' => 230,
|
||||
'𝉂' => 230,
|
||||
'𝉃' => 230,
|
||||
'𝉄' => 230,
|
||||
'𞀀' => 230,
|
||||
'𞀁' => 230,
|
||||
'𞀂' => 230,
|
||||
'𞀃' => 230,
|
||||
'𞀄' => 230,
|
||||
'𞀅' => 230,
|
||||
'𞀆' => 230,
|
||||
'𞀈' => 230,
|
||||
'𞀉' => 230,
|
||||
'𞀊' => 230,
|
||||
'𞀋' => 230,
|
||||
'𞀌' => 230,
|
||||
'𞀍' => 230,
|
||||
'𞀎' => 230,
|
||||
'𞀏' => 230,
|
||||
'𞀐' => 230,
|
||||
'𞀑' => 230,
|
||||
'𞀒' => 230,
|
||||
'𞀓' => 230,
|
||||
'𞀔' => 230,
|
||||
'𞀕' => 230,
|
||||
'𞀖' => 230,
|
||||
'𞀗' => 230,
|
||||
'𞀘' => 230,
|
||||
'𞀛' => 230,
|
||||
'𞀜' => 230,
|
||||
'𞀝' => 230,
|
||||
'𞀞' => 230,
|
||||
'𞀟' => 230,
|
||||
'𞀠' => 230,
|
||||
'𞀡' => 230,
|
||||
'𞀣' => 230,
|
||||
'𞀤' => 230,
|
||||
'𞀦' => 230,
|
||||
'𞀧' => 230,
|
||||
'𞀨' => 230,
|
||||
'𞀩' => 230,
|
||||
'𞀪' => 230,
|
||||
'𞄰' => 230,
|
||||
'𞄱' => 230,
|
||||
'𞄲' => 230,
|
||||
'𞄳' => 230,
|
||||
'𞄴' => 230,
|
||||
'𞄵' => 230,
|
||||
'𞄶' => 230,
|
||||
'𞋬' => 230,
|
||||
'𞋭' => 230,
|
||||
'𞋮' => 230,
|
||||
'𞋯' => 230,
|
||||
'𞣐' => 220,
|
||||
'𞣑' => 220,
|
||||
'𞣒' => 220,
|
||||
'𞣓' => 220,
|
||||
'𞣔' => 220,
|
||||
'𞣕' => 220,
|
||||
'𞣖' => 220,
|
||||
'𞥄' => 230,
|
||||
'𞥅' => 230,
|
||||
'𞥆' => 230,
|
||||
'𞥇' => 230,
|
||||
'𞥈' => 230,
|
||||
'𞥉' => 230,
|
||||
'𞥊' => 7,
|
||||
);
|
||||
+3695
File diff suppressed because it is too large
Load Diff
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Intl\Normalizer as p;
|
||||
|
||||
if (!function_exists('normalizer_is_normalized')) {
|
||||
function normalizer_is_normalized($s, $form = p\Normalizer::NFC) { return p\Normalizer::isNormalized($s, $form); }
|
||||
}
|
||||
if (!function_exists('normalizer_normalize')) {
|
||||
function normalizer_normalize($s, $form = p\Normalizer::NFC) { return p\Normalizer::normalize($s, $form); }
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user