commit vendor

This commit is contained in:
2025-11-11 14:49:30 +01:00
parent f33121a308
commit 6d03080c00
2436 changed files with 483781 additions and 0 deletions

View File

@ -0,0 +1,2 @@
Copyright (c) 2019-2020, Laminas Foundation.
All rights reserved. (https://getlaminas.org/)

27
vendor/laminas/laminas-i18n/LICENSE.md vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2019-2020, Laminas Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of Laminas Foundation nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,187 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n;
use Laminas\ServiceManager\Factory\InvokableFactory;
class ConfigProvider
{
/**
* Return general-purpose laminas-i18n configuration.
*
* @return array
*/
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
'filters' => $this->getFilterConfig(),
'validators' => $this->getValidatorConfig(),
'view_helpers' => $this->getViewHelperConfig(),
];
}
/**
* Return application-level dependency configuration.
*
* @return array
*/
public function getDependencyConfig()
{
return [
'aliases' => [
'TranslatorPluginManager' => Translator\LoaderPluginManager::class,
// Legacy Zend Framework aliases
\Zend\I18n\Translator\TranslatorInterface::class => Translator\TranslatorInterface::class,
\Zend\I18n\Translator\LoaderPluginManager::class => Translator\LoaderPluginManager::class,
],
'factories' => [
Translator\TranslatorInterface::class => Translator\TranslatorServiceFactory::class,
Translator\LoaderPluginManager::class => Translator\LoaderPluginManagerFactory::class,
],
];
}
/**
* Return laminas-filter configuration.
*
* @return array
*/
public function getFilterConfig()
{
return [
'aliases' => [
'alnum' => Filter\Alnum::class,
'Alnum' => Filter\Alnum::class,
'alpha' => Filter\Alpha::class,
'Alpha' => Filter\Alpha::class,
'numberformat' => Filter\NumberFormat::class,
'numberFormat' => Filter\NumberFormat::class,
'NumberFormat' => Filter\NumberFormat::class,
'numberparse' => Filter\NumberParse::class,
'numberParse' => Filter\NumberParse::class,
'NumberParse' => Filter\NumberParse::class,
// Legacy Zend Framework aliases
\Zend\I18n\Filter\Alnum::class => Filter\Alnum::class,
\Zend\I18n\Filter\Alpha::class => Filter\Alpha::class,
\Zend\I18n\Filter\NumberFormat::class => Filter\NumberFormat::class,
\Zend\I18n\Filter\NumberParse::class => Filter\NumberParse::class,
],
'factories' => [
Filter\Alnum::class => InvokableFactory::class,
Filter\Alpha::class => InvokableFactory::class,
Filter\NumberFormat::class => InvokableFactory::class,
Filter\NumberParse::class => InvokableFactory::class,
],
];
}
/**
* Return laminas-validator configuration.
*
* @return array
*/
public function getValidatorConfig()
{
return [
'aliases' => [
'alnum' => Validator\Alnum::class,
'Alnum' => Validator\Alnum::class,
'alpha' => Validator\Alpha::class,
'Alpha' => Validator\Alpha::class,
'datetime' => Validator\DateTime::class,
'dateTime' => Validator\DateTime::class,
'DateTime' => Validator\DateTime::class,
'float' => Validator\IsFloat::class,
'Float' => Validator\IsFloat::class,
'int' => Validator\IsInt::class,
'Int' => Validator\IsInt::class,
'isfloat' => Validator\IsFloat::class,
'isFloat' => Validator\IsFloat::class,
'IsFloat' => Validator\IsFloat::class,
'isint' => Validator\IsInt::class,
'isInt' => Validator\IsInt::class,
'IsInt' => Validator\IsInt::class,
'phonenumber' => Validator\PhoneNumber::class,
'phoneNumber' => Validator\PhoneNumber::class,
'PhoneNumber' => Validator\PhoneNumber::class,
'postcode' => Validator\PostCode::class,
'postCode' => Validator\PostCode::class,
'PostCode' => Validator\PostCode::class,
// Legacy Zend Framework aliases
\Zend\I18n\Validator\Alnum::class => Validator\Alnum::class,
\Zend\I18n\Validator\Alpha::class => Validator\Alpha::class,
\Zend\I18n\Validator\DateTime::class => Validator\DateTime::class,
\Zend\I18n\Validator\IsFloat::class => Validator\IsFloat::class,
\Zend\I18n\Validator\IsInt::class => Validator\IsInt::class,
\Zend\I18n\Validator\PhoneNumber::class => Validator\PhoneNumber::class,
\Zend\I18n\Validator\PostCode::class => Validator\PostCode::class,
],
'factories' => [
Validator\Alnum::class => InvokableFactory::class,
Validator\Alpha::class => InvokableFactory::class,
Validator\DateTime::class => InvokableFactory::class,
Validator\IsFloat::class => InvokableFactory::class,
Validator\IsInt::class => InvokableFactory::class,
Validator\PhoneNumber::class => InvokableFactory::class,
Validator\PostCode::class => InvokableFactory::class,
],
];
}
/**
* Return laminas-view helper configuration.
*
* Obsoletes View\HelperConfig.
*
* @return array
*/
public function getViewHelperConfig()
{
return [
'aliases' => [
'currencyformat' => View\Helper\CurrencyFormat::class,
'currencyFormat' => View\Helper\CurrencyFormat::class,
'CurrencyFormat' => View\Helper\CurrencyFormat::class,
'dateformat' => View\Helper\DateFormat::class,
'dateFormat' => View\Helper\DateFormat::class,
'DateFormat' => View\Helper\DateFormat::class,
'numberformat' => View\Helper\NumberFormat::class,
'numberFormat' => View\Helper\NumberFormat::class,
'NumberFormat' => View\Helper\NumberFormat::class,
'plural' => View\Helper\Plural::class,
'Plural' => View\Helper\Plural::class,
'translate' => View\Helper\Translate::class,
'Translate' => View\Helper\Translate::class,
'translateplural' => View\Helper\TranslatePlural::class,
'translatePlural' => View\Helper\TranslatePlural::class,
'TranslatePlural' => View\Helper\TranslatePlural::class,
// Legacy Zend Framework aliases
\Zend\I18n\View\Helper\CurrencyFormat::class => View\Helper\CurrencyFormat::class,
\Zend\I18n\View\Helper\DateFormat::class => View\Helper\DateFormat::class,
\Zend\I18n\View\Helper\NumberFormat::class => View\Helper\NumberFormat::class,
\Zend\I18n\View\Helper\Plural::class => View\Helper\Plural::class,
\Zend\I18n\View\Helper\Translate::class => View\Helper\Translate::class,
\Zend\I18n\View\Helper\TranslatePlural::class => View\Helper\TranslatePlural::class,
],
'factories' => [
View\Helper\CurrencyFormat::class => InvokableFactory::class,
View\Helper\DateFormat::class => InvokableFactory::class,
View\Helper\NumberFormat::class => InvokableFactory::class,
View\Helper\Plural::class => InvokableFactory::class,
View\Helper\Translate::class => InvokableFactory::class,
View\Helper\TranslatePlural::class => InvokableFactory::class,
],
];
}
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
interface ExceptionInterface
{
}

View File

@ -0,0 +1,15 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
use DomainException;
class ExtensionNotLoadedException extends DomainException implements ExceptionInterface
{
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
class ParseException extends RuntimeException implements ExceptionInterface
{
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
class RangeException extends \RangeException implements ExceptionInterface
{
}

View File

@ -0,0 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@ -0,0 +1,54 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Filter;
use Laminas\Filter\AbstractFilter;
use Laminas\I18n\Exception;
use Locale;
abstract class AbstractLocale extends AbstractFilter
{
/**
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct()
{
if (! extension_loaded('intl')) {
throw new Exception\ExtensionNotLoadedException(sprintf(
'%s component requires the intl PHP extension',
__NAMESPACE__
));
}
}
/**
* Sets the locale option
*
* @param string|null $locale
* @return $this
*/
public function setLocale($locale = null)
{
$this->options['locale'] = $locale;
return $this;
}
/**
* Returns the locale option
*
* @return string
*/
public function getLocale()
{
if (! isset($this->options['locale'])) {
$this->options['locale'] = Locale::getDefault();
}
return $this->options['locale'];
}
}

View File

@ -0,0 +1,96 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Filter;
use Laminas\Stdlib\StringUtils;
use Locale;
use Traversable;
class Alnum extends AbstractLocale
{
/**
* @var array
*/
protected $options = [
'locale' => null,
'allow_white_space' => false,
];
/**
* Sets default option values for this instance
*
* @param array|Traversable|bool|null $allowWhiteSpaceOrOptions
* @param string|null $locale
*/
public function __construct($allowWhiteSpaceOrOptions = null, $locale = null)
{
parent::__construct();
if ($allowWhiteSpaceOrOptions !== null) {
if (static::isOptions($allowWhiteSpaceOrOptions)) {
$this->setOptions($allowWhiteSpaceOrOptions);
} else {
$this->setAllowWhiteSpace($allowWhiteSpaceOrOptions);
$this->setLocale($locale);
}
}
}
/**
* Sets the allowWhiteSpace option
*
* @param bool $flag
* @return $this
*/
public function setAllowWhiteSpace($flag = true)
{
$this->options['allow_white_space'] = (bool) $flag;
return $this;
}
/**
* Whether white space is allowed
*
* @return bool
*/
public function getAllowWhiteSpace()
{
return $this->options['allow_white_space'];
}
/**
* Defined by Laminas\Filter\FilterInterface
*
* Returns $value as string with all non-alphanumeric characters removed
*
* @param string|array $value
* @return string|array
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
$whiteSpace = $this->options['allow_white_space'] ? '\s' : '';
$language = Locale::getPrimaryLanguage($this->getLocale());
if (! StringUtils::hasPcreUnicodeSupport()) {
// POSIX named classes are not supported, use alternative a-zA-Z0-9 match
$pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/';
} elseif (in_array($language, ['ja', 'ko', 'zh'], true)) {
// Use english alphabet
$pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/u';
} else {
// Use native language alphabet
$pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u';
}
return preg_replace($pattern, '', $value);
}
}

View File

@ -0,0 +1,46 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Filter;
use Laminas\Stdlib\StringUtils;
use Locale;
class Alpha extends Alnum
{
/**
* Defined by Laminas\Filter\FilterInterface
*
* Returns the string $value, removing all but alphabetic characters
*
* @param string|array $value
* @return string|array
*/
public function filter($value)
{
if (! is_scalar($value) && ! is_array($value)) {
return $value;
}
$whiteSpace = $this->options['allow_white_space'] ? '\s' : '';
$language = Locale::getPrimaryLanguage($this->getLocale());
if (! StringUtils::hasPcreUnicodeSupport()) {
// POSIX named classes are not supported, use alternative [a-zA-Z] match
$pattern = '/[^a-zA-Z' . $whiteSpace . ']/';
} elseif (in_array($language, ['ja', 'ko', 'zh'], true)) {
// Use english alphabet
$pattern = '/[^a-zA-Z' . $whiteSpace . ']/u';
} else {
// Use native language alphabet
$pattern = '/[^\p{L}' . $whiteSpace . ']/u';
}
return preg_replace($pattern, '', $value);
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Filter;
use Laminas\Stdlib\ErrorHandler;
class NumberFormat extends NumberParse
{
/**
* Defined by Laminas\Filter\FilterInterface
*
* @see \Laminas\Filter\FilterInterface::filter()
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_scalar($value)) {
return $value;
}
if (! is_int($value) && ! is_float($value)) {
$result = parent::filter($value);
} else {
ErrorHandler::start();
$result = $this->getFormatter()->format($value, $this->getType());
ErrorHandler::stop();
}
if (false !== $result) {
return $result;
}
return $value;
}
}

View File

@ -0,0 +1,161 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Filter;
use Laminas\I18n\Exception;
use Laminas\Stdlib\ErrorHandler;
use NumberFormatter;
use Traversable;
class NumberParse extends AbstractLocale
{
protected $options = [
'locale' => null,
'style' => NumberFormatter::DEFAULT_STYLE,
'type' => NumberFormatter::TYPE_DOUBLE
];
/**
* @var NumberFormatter
*/
protected $formatter;
/**
* @param array|Traversable|string|null $localeOrOptions
* @param int $style
* @param int $type
*/
public function __construct(
$localeOrOptions = null,
$style = NumberFormatter::DEFAULT_STYLE,
$type = NumberFormatter::TYPE_DOUBLE
) {
parent::__construct();
if ($localeOrOptions !== null) {
if ($localeOrOptions instanceof Traversable) {
$localeOrOptions = iterator_to_array($localeOrOptions);
}
if (! is_array($localeOrOptions)) {
$this->setLocale($localeOrOptions);
$this->setStyle($style);
$this->setType($type);
} else {
$this->setOptions($localeOrOptions);
}
}
}
/**
* @param string|null $locale
* @return $this
*/
public function setLocale($locale = null)
{
$this->options['locale'] = $locale;
$this->formatter = null;
return $this;
}
/**
* @param int $style
* @return $this
*/
public function setStyle($style)
{
$this->options['style'] = (int) $style;
$this->formatter = null;
return $this;
}
/**
* @return int
*/
public function getStyle()
{
return $this->options['style'];
}
/**
* @param int $type
* @return $this
*/
public function setType($type)
{
$this->options['type'] = (int) $type;
return $this;
}
/**
* @return int
*/
public function getType()
{
return $this->options['type'];
}
/**
* @param NumberFormatter $formatter
* @return $this
*/
public function setFormatter(NumberFormatter $formatter)
{
$this->formatter = $formatter;
return $this;
}
/**
* @return NumberFormatter
* @throws Exception\RuntimeException
*/
public function getFormatter()
{
if ($this->formatter === null) {
$formatter = NumberFormatter::create($this->getLocale(), $this->getStyle());
if (! $formatter) {
throw new Exception\RuntimeException(
'Can not create NumberFormatter instance; ' . intl_get_error_message()
);
}
$this->formatter = $formatter;
}
return $this->formatter;
}
/**
* Defined by Laminas\Filter\FilterInterface
*
* @see \Laminas\Filter\FilterInterface::filter()
* @param mixed $value
* @return mixed
*/
public function filter($value)
{
if (! is_int($value)
&& ! is_float($value)
) {
ErrorHandler::start();
$result = $this->getFormatter()->parse(
$value,
$this->getType()
);
ErrorHandler::stop();
if (false !== $result) {
return $result;
}
}
return $value;
}
}

View File

@ -0,0 +1,48 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n;
class Module
{
/**
* Return laminas-i18n configuration for laminas-mvc application.
*
* @return array
*/
public function getConfig()
{
$provider = new ConfigProvider();
return [
'filters' => $provider->getFilterConfig(),
'service_manager' => $provider->getDependencyConfig(),
'validators' => $provider->getValidatorConfig(),
'view_helpers' => $provider->getViewHelperConfig(),
];
}
/**
* Register a specification for the TranslatorPluginManager with the ServiceListener.
*
* @param \Laminas\ModuleManager\ModuleManager $moduleManager
* @return void
*/
public function init($moduleManager)
{
$event = $moduleManager->getEvent();
$container = $event->getParam('ServiceManager');
$serviceListener = $container->get('ServiceListener');
$serviceListener->addServiceManager(
'TranslatorPluginManager',
'translator_plugins',
'Laminas\ModuleManager\Feature\TranslatorPluginProviderInterface',
'getTranslatorPluginConfig'
);
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
/**
* Abstract file loader implementation; provides facilities around resolving
* files via the include_path.
*/
abstract class AbstractFileLoader implements FileLoaderInterface
{
/**
* Whether or not to consult the include_path when locating files
*
* @var bool
*/
protected $useIncludePath = false;
/**
* Indicate whether or not to use the include_path to resolve translation files
*
* @param bool $flag
* @return self
*/
public function setUseIncludePath($flag = true)
{
$this->useIncludePath = (bool) $flag;
return $this;
}
/**
* Are we using the include_path to resolve translation files?
*
* @return bool
*/
public function useIncludePath()
{
return $this->useIncludePath;
}
/**
* Resolve a translation file
*
* Checks if the file exists and is readable, returning a boolean false if not; if the "useIncludePath"
* flag is enabled, it will attempt to resolve the file from the
* include_path if the file does not exist on the current working path.
*
* @param string $filename
* @return string|false
*/
protected function resolveFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
if (! $this->useIncludePath()) {
return false;
}
return $this->resolveViaIncludePath($filename);
}
return $filename;
}
/**
* Resolve a translation file via the include_path
*
* @param string $filename
* @return string|false
*/
protected function resolveViaIncludePath($filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
if (! $resolvedIncludePath || ! is_file($resolvedIncludePath) || ! is_readable($resolvedIncludePath)) {
return false;
}
return $resolvedIncludePath;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Translator\TextDomain;
/**
* File loader interface.
*/
interface FileLoaderInterface
{
/**
* Load translations from a file.
*
* @param string $locale
* @param string $filename
* @return TextDomain|null
*/
public function load($locale, $filename);
}

View File

@ -0,0 +1,190 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
use Laminas\Stdlib\ErrorHandler;
/**
* Gettext loader.
*/
class Gettext extends AbstractFileLoader
{
/**
* Current file pointer.
*
* @var resource
*/
protected $file;
/**
* Whether the current file is little endian.
*
* @var bool
*/
protected $littleEndian;
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedFile = $this->resolveFile($filename);
if (! $resolvedFile) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$textDomain = new TextDomain();
ErrorHandler::start();
$this->file = fopen($resolvedFile, 'rb');
$error = ErrorHandler::stop();
if (false === $this->file) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not open file %s for reading',
$filename
), 0, $error);
}
// Verify magic number
$magic = fread($this->file, 4);
if ($magic === "\x95\x04\x12\xde") {
$this->littleEndian = false;
} elseif ($magic === "\xde\x12\x04\x95") {
$this->littleEndian = true;
} else {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s is not a valid gettext file',
$filename
));
}
// Verify major revision (only 0 and 1 supported)
$majorRevision = ($this->readInteger() >> 16);
if ($majorRevision !== 0 && $majorRevision !== 1) {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s has an unknown major revision',
$filename
));
}
// Gather main information
$numStrings = $this->readInteger();
$originalStringTableOffset = $this->readInteger();
$translationStringTableOffset = $this->readInteger();
// Usually there follow size and offset of the hash table, but we have
// no need for it, so we skip them.
fseek($this->file, $originalStringTableOffset);
$originalStringTable = $this->readIntegerList(2 * $numStrings);
fseek($this->file, $translationStringTableOffset);
$translationStringTable = $this->readIntegerList(2 * $numStrings);
// Read in all translations
for ($current = 0; $current < $numStrings; $current++) {
$sizeKey = $current * 2 + 1;
$offsetKey = $current * 2 + 2;
$originalStringSize = $originalStringTable[$sizeKey];
$originalStringOffset = $originalStringTable[$offsetKey];
$translationStringSize = $translationStringTable[$sizeKey];
$translationStringOffset = $translationStringTable[$offsetKey];
$originalString = [''];
if ($originalStringSize > 0) {
fseek($this->file, $originalStringOffset);
$originalString = explode("\0", fread($this->file, $originalStringSize));
}
if ($translationStringSize > 0) {
fseek($this->file, $translationStringOffset);
$translationString = explode("\0", fread($this->file, $translationStringSize));
if (isset($originalString[1], $translationString[1])) {
$textDomain[$originalString[0]] = $translationString;
array_shift($originalString);
foreach ($originalString as $string) {
if (! isset($textDomain[$string])) {
$textDomain[$string] = '';
}
}
} else {
$textDomain[$originalString[0]] = $translationString[0];
}
}
}
// Read header entries
if ($textDomain->offsetExists('')) {
$rawHeaders = explode("\n", trim($textDomain['']));
foreach ($rawHeaders as $rawHeader) {
list($header, $content) = explode(':', $rawHeader, 2);
if (strtolower(trim($header)) === 'plural-forms') {
$textDomain->setPluralRule(PluralRule::fromString($content));
}
}
unset($textDomain['']);
}
fclose($this->file);
return $textDomain;
}
/**
* Read a single integer from the current file.
*
* @return int
*/
protected function readInteger()
{
if ($this->littleEndian) {
$result = unpack('Vint', fread($this->file, 4));
} else {
$result = unpack('Nint', fread($this->file, 4));
}
return $result['int'];
}
/**
* Read an integer from the current file.
*
* @param int $num
* @return int
*/
protected function readIntegerList($num)
{
if ($this->littleEndian) {
return unpack('V' . $num, fread($this->file, 4 * $num));
}
return unpack('N' . $num, fread($this->file, 4 * $num));
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\Config\Reader\Ini as IniReader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP INI format loader.
*/
class Ini extends AbstractFileLoader
{
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
$fromIncludePath = ($resolvedIncludePath !== false) ? $resolvedIncludePath : $filename;
if (! $fromIncludePath || ! is_file($fromIncludePath) || ! is_readable($fromIncludePath)) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$messages = [];
$iniReader = new IniReader();
$messagesNamespaced = $iniReader->fromFile($fromIncludePath);
$list = $messagesNamespaced;
if (isset($messagesNamespaced['translation'])) {
$list = $messagesNamespaced['translation'];
}
foreach ($list as $message) {
if (! is_array($message) || count($message) < 2) {
throw new Exception\InvalidArgumentException(
'Each INI row must be an array with message and translation'
);
}
if (isset($message['message'], $message['translation'])) {
$messages[$message['message']] = $message['translation'];
continue;
}
$messages[array_shift($message)] = array_shift($message);
}
if (! is_array($messages)) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected an array, but received %s',
gettype($messages)
));
}
$textDomain = new TextDomain($messages);
if (isset($messagesNamespaced['plural']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($messagesNamespaced['plural']['plural_forms'])
);
}
return $textDomain;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP array loader.
*/
class PhpArray extends AbstractFileLoader
{
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
$fromIncludePath = ($resolvedIncludePath !== false) ? $resolvedIncludePath : $filename;
if (! $fromIncludePath || ! is_file($fromIncludePath) || ! is_readable($fromIncludePath)) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$messages = include $fromIncludePath;
if (! is_array($messages)) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected an array, but received %s',
gettype($messages)
));
}
$textDomain = new TextDomain($messages);
if ($textDomain->offsetExists('')) {
if (isset($textDomain['']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($textDomain['']['plural_forms'])
);
}
unset($textDomain['']);
}
return $textDomain;
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP Memory array loader.
*/
class PhpMemoryArray implements RemoteLoaderInterface
{
/**
* @var array
*/
protected $messages;
public function __construct($messages)
{
$this->messages = $messages;
}
/**
* Load translations from a remote source.
*
* @param string $locale
* @param string $textDomain
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $textDomain)
{
if (! is_array($this->messages)) {
throw new Exception\InvalidArgumentException(
sprintf('Expected an array, but received %s', gettype($this->messages))
);
}
if (! isset($this->messages[$textDomain])) {
throw new Exception\InvalidArgumentException(
sprintf('Expected textdomain "%s" to be an array, but it is not set', $textDomain)
);
}
if (! isset($this->messages[$textDomain][$locale])) {
throw new Exception\InvalidArgumentException(
sprintf('Expected locale "%s" to be an array, but it is not set', $locale)
);
}
$textDomain = new TextDomain($this->messages[$textDomain][$locale]);
if ($textDomain->offsetExists('')) {
if (isset($textDomain['']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($textDomain['']['plural_forms'])
);
}
unset($textDomain['']);
}
return $textDomain;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Translator\TextDomain;
/**
* Remote loader interface.
*/
interface RemoteLoaderInterface
{
/**
* Load translations from a remote source.
*
* @param string $locale
* @param string $textDomain
* @return TextDomain|null
*/
public function load($locale, $textDomain);
}

View File

@ -0,0 +1,138 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
use Laminas\I18n\Exception;
use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Laminas\ServiceManager\Factory\InvokableFactory;
/**
* Plugin manager implementation for translation loaders.
*
* Enforces that loaders retrieved are either instances of
* Loader\FileLoaderInterface or Loader\RemoteLoaderInterface. Additionally,
* it registers a number of default loaders.
*
* If you are wanting to use the ability to load translation files from the
* include_path, you will need to create a factory to override the defaults
* defined in this class. A simple factory might look like:
*
* <code>
* function ($translators) {
* $adapter = new Gettext();
* $adapter->setUseIncludePath(true);
* return $adapter;
* }
* </code>
*
* You may need to override the Translator service factory to make this happen
* more easily. That can be done by extending it:
*
* <code>
* use Laminas\I18n\Translator\TranslatorServiceFactory;
* // or Laminas\Mvc\I18n\TranslatorServiceFactory
* use Laminas\ServiceManager\ServiceLocatorInterface;
*
* class MyTranslatorServiceFactory extends TranslatorServiceFactory
* {
* public function createService(ServiceLocatorInterface $services)
* {
* $translator = parent::createService($services);
* $translator->getLoaderPluginManager()->setFactory(...);
* return $translator;
* }
* }
* </code>
*
* You would then specify your custom factory in your service configuration.
*/
class LoaderPluginManager extends AbstractPluginManager
{
protected $aliases = [
'gettext' => Loader\Gettext::class,
'getText' => Loader\Gettext::class,
'GetText' => Loader\Gettext::class,
'ini' => Loader\Ini::class,
'phparray' => Loader\PhpArray::class,
'phpArray' => Loader\PhpArray::class,
'PhpArray' => Loader\PhpArray::class,
// Legacy Zend Framework aliases
\Zend\I18n\Translator\Loader\Gettext::class => Loader\Gettext::class,
\Zend\I18n\Translator\Loader\Ini::class => Loader\Ini::class,
\Zend\I18n\Translator\Loader\PhpArray::class => Loader\PhpArray::class,
// v2 normalized FQCNs
'zendi18ntranslatorloadergettext' => Loader\Gettext::class,
'zendi18ntranslatorloaderini' => Loader\Ini::class,
'zendi18ntranslatorloaderphparray' => Loader\PhpArray::class,
];
protected $factories = [
Loader\Gettext::class => InvokableFactory::class,
Loader\Ini::class => InvokableFactory::class,
Loader\PhpArray::class => InvokableFactory::class,
// Legacy (v2) due to alias resolution; canonical form of resolved
// alias is used to look up the factory, while the non-normalized
// resolved alias is used as the requested name passed to the factory.
'laminasi18ntranslatorloadergettext' => InvokableFactory::class,
'laminasi18ntranslatorloaderini' => InvokableFactory::class,
'laminasi18ntranslatorloaderphparray' => InvokableFactory::class
];
/**
* Validate the plugin.
*
* Checks that the filter loaded is an instance of
* Loader\FileLoaderInterface or Loader\RemoteLoaderInterface.
*
* @param mixed $plugin
* @return void
* @throws Exception\RuntimeException if invalid
*/
public function validate($plugin)
{
if ($plugin instanceof Loader\FileLoaderInterface || $plugin instanceof Loader\RemoteLoaderInterface) {
// we're okay
return;
}
throw new InvalidServiceException(sprintf(
'Plugin of type %s is invalid; must implement %s\Loader\FileLoaderInterface '
. 'or %s\Loader\RemoteLoaderInterface',
(is_object($plugin) ? get_class($plugin) : gettype($plugin)),
__NAMESPACE__,
__NAMESPACE__
));
}
/**
* Validate the plugin is of the expected type (v2).
*
* Proxies to `validate()`.
*
* @param mixed $plugin
* @throws Exception\RuntimeException
*/
public function validatePlugin($plugin)
{
try {
$this->validate($plugin);
} catch (InvalidServiceException $e) {
throw new Exception\RuntimeException(sprintf(
'Plugin of type %s is invalid; must implement %s\Loader\FileLoaderInterface '
. 'or %s\Loader\RemoteLoaderInterface',
(is_object($plugin) ? get_class($plugin) : gettype($plugin)),
__NAMESPACE__,
__NAMESPACE__
));
}
}
}

View File

@ -0,0 +1,83 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Config;
use Laminas\ServiceManager\FactoryInterface;
use Laminas\ServiceManager\ServiceLocatorInterface;
class LoaderPluginManagerFactory implements FactoryInterface
{
/**
* laminas-servicemanager v2 options passed to factory.
*
* @param array
*/
protected $creationOptions = [];
/**
* Create and return a LoaderPluginManager.
*
* @param ContainerInterface $container
* @param string $name
* @param null|array $options
* @return LoaderPluginManager
*/
public function __invoke(ContainerInterface $container, $name, array $options = null)
{
$options = $options ?: [];
$pluginManager = new LoaderPluginManager($container, $options);
// If this is in a laminas-mvc application, the ServiceListener will inject
// merged configuration during bootstrap.
if ($container->has('ServiceListener')) {
return $pluginManager;
}
// If we do not have a config service, nothing more to do
if (! $container->has('config')) {
return $pluginManager;
}
$config = $container->get('config');
// If we do not have translator_plugins configuration, nothing more to do
if (! isset($config['translator_plugins']) || ! is_array($config['translator_plugins'])) {
return $pluginManager;
}
// Wire service configuration for translator_plugins
(new Config($config['translator_plugins']))->configureServiceManager($pluginManager);
return $pluginManager;
}
/**
* laminas-servicemanager v2 factory to return LoaderPluginManager
*
* @param ServiceLocatorInterface $container
* @return LoaderPluginManager
*/
public function createService(ServiceLocatorInterface $container)
{
return $this($container, 'TranslatorPluginManager', $this->creationOptions);
}
/**
* v2 support for instance creation options.
*
* @param array $options
* @return void
*/
public function setCreationOptions(array $options)
{
$this->creationOptions = $options;
}
}

View File

@ -0,0 +1,377 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Plural;
use Laminas\I18n\Exception;
/**
* Plural rule parser.
*
* This plural rule parser is implemented after the article "Top Down Operator
* Precedence" described in <http://javascript.crockford.com/tdop/tdop.html>.
*/
class Parser
{
/**
* String to parse.
*
* @var string
*/
protected $string;
/**
* Current lexer position in the string.
*
* @var int
*/
protected $currentPos;
/**
* Current token.
*
* @var Symbol
*/
protected $currentToken;
/**
* Table of symbols.
*
* @var Symbol[]
*/
protected $symbolTable = [];
/**
* Create a new plural parser.
*
*/
public function __construct()
{
$this->populateSymbolTable();
}
/**
* Populate the symbol table.
*
* @return void
*/
protected function populateSymbolTable()
{
// Ternary operators
$this->registerSymbol('?', 20)->setLeftDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self, Symbol $left) {
$self->first = $left;
$self->second = $self->parser->expression();
$self->parser->advance(':');
$self->third = $self->parser->expression();
return $self;
}
// @codingStandardsIgnoreEnd
);
$this->registerSymbol(':');
// Boolean operators
$this->registerLeftInfixSymbol('||', 30);
$this->registerLeftInfixSymbol('&&', 40);
// Equal operators
$this->registerLeftInfixSymbol('==', 50);
$this->registerLeftInfixSymbol('!=', 50);
// Compare operators
$this->registerLeftInfixSymbol('>', 50);
$this->registerLeftInfixSymbol('<', 50);
$this->registerLeftInfixSymbol('>=', 50);
$this->registerLeftInfixSymbol('<=', 50);
// Add operators
$this->registerLeftInfixSymbol('-', 60);
$this->registerLeftInfixSymbol('+', 60);
// Multiply operators
$this->registerLeftInfixSymbol('*', 70);
$this->registerLeftInfixSymbol('/', 70);
$this->registerLeftInfixSymbol('%', 70);
// Not operator
$this->registerPrefixSymbol('!', 80);
// Literals
$this->registerSymbol('n')->setNullDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self) {
return $self;
}
// @codingStandardsIgnoreEnd
);
$this->registerSymbol('number')->setNullDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self) {
return $self;
}
// @codingStandardsIgnoreEnd
);
// Parentheses
$this->registerSymbol('(')->setNullDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self) {
$expression = $self->parser->expression();
$self->parser->advance(')');
return $expression;
}
// @codingStandardsIgnoreEnd
);
$this->registerSymbol(')');
// Eof
$this->registerSymbol('eof');
}
/**
* Register a left infix symbol.
*
* @param string $id
* @param int $leftBindingPower
* @return void
*/
protected function registerLeftInfixSymbol($id, $leftBindingPower)
{
$this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self, Symbol $left) use ($leftBindingPower) {
$self->first = $left;
$self->second = $self->parser->expression($leftBindingPower);
return $self;
}
// @codingStandardsIgnoreEnd
);
}
/**
* Register a right infix symbol.
*
* @param string $id
* @param int $leftBindingPower
* @return void
*/
protected function registerRightInfixSymbol($id, $leftBindingPower)
{
$this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self, Symbol $left) use ($leftBindingPower) {
$self->first = $left;
$self->second = $self->parser->expression($leftBindingPower - 1);
return $self;
}
// @codingStandardsIgnoreEnd
);
}
/**
* Register a prefix symbol.
*
* @param string $id
* @param int $leftBindingPower
* @return void
*/
protected function registerPrefixSymbol($id, $leftBindingPower)
{
$this->registerSymbol($id, $leftBindingPower)->setNullDenotationGetter(
// @codingStandardsIgnoreStart Generic.WhiteSpace.ScopeIndent.IncorrectExact
static function (Symbol $self) use ($leftBindingPower) {
$self->first = $self->parser->expression($leftBindingPower);
$self->second = null;
return $self;
}
// @codingStandardsIgnoreEnd
);
}
/**
* Register a symbol.
*
* @param string $id
* @param int $leftBindingPower
* @return Symbol
*/
protected function registerSymbol($id, $leftBindingPower = 0)
{
if (isset($this->symbolTable[$id])) {
$symbol = $this->symbolTable[$id];
$symbol->leftBindingPower = max(
$symbol->leftBindingPower,
$leftBindingPower
);
} else {
$symbol = new Symbol($this, $id, $leftBindingPower);
$this->symbolTable[$id] = $symbol;
}
return $symbol;
}
/**
* Get a new symbol.
*
* @param string $id
* @return Symbol
*/
protected function getSymbol($id)
{
if (! isset($this->symbolTable[$id])) {
// Unknown symbol exception
}
return clone $this->symbolTable[$id];
}
/**
* Parse a string.
*
* @param string $string
* @return Symbol
*/
public function parse($string)
{
$this->string = $string . "\0";
$this->currentPos = 0;
$this->currentToken = $this->getNextToken();
return $this->expression();
}
/**
* Parse an expression.
*
* @param int $rightBindingPower
* @return Symbol
*/
public function expression($rightBindingPower = 0)
{
$token = $this->currentToken;
$this->currentToken = $this->getNextToken();
$left = $token->getNullDenotation();
while ($rightBindingPower < $this->currentToken->leftBindingPower) {
$token = $this->currentToken;
$this->currentToken = $this->getNextToken();
$left = $token->getLeftDenotation($left);
}
return $left;
}
/**
* Advance the current token and optionally check the old token id.
*
* @param string $id
* @return void
* @throws Exception\ParseException
*/
public function advance($id = null)
{
if ($id !== null && $this->currentToken->id !== $id) {
throw new Exception\ParseException(
sprintf('Expected token with id %s but received %s', $id, $this->currentToken->id)
);
}
$this->currentToken = $this->getNextToken();
}
/**
* Get the next token.
*
* @return Symbol
* @throws Exception\ParseException
*/
protected function getNextToken()
{
while ($this->string[$this->currentPos] === ' ' || $this->string[$this->currentPos] === "\t") {
$this->currentPos++;
}
$result = $this->string[$this->currentPos++];
$value = null;
switch ($result) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
while (ctype_digit($this->string[$this->currentPos])) {
$result .= $this->string[$this->currentPos++];
}
$id = 'number';
$value = (int) $result;
break;
case '=':
case '&':
case '|':
if ($this->string[$this->currentPos] === $result) {
$this->currentPos++;
$id = $result . $result;
} else {
// Yield error
}
break;
case '!':
case '<':
case '>':
if ($this->string[$this->currentPos] === '=') {
$this->currentPos++;
$result .= '=';
}
$id = $result;
break;
case '*':
case '/':
case '%':
case '+':
case '-':
case 'n':
case '?':
case ':':
case '(':
case ')':
$id = $result;
break;
case ';':
case "\n":
case "\0":
$id = 'eof';
$this->currentPos--;
break;
default:
throw new Exception\ParseException(sprintf(
'Found invalid character "%s" in input stream',
$result
));
}
$token = $this->getSymbol($id);
$token->value = $value;
return $token;
}
}

View File

@ -0,0 +1,252 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Plural;
use Laminas\I18n\Exception;
/**
* Plural rule evaluator.
*/
class Rule
{
/**
* Parser instance.
*
* @var Parser
*/
protected static $parser;
/**
* Abstract syntax tree.
*
* @var array
*/
protected $ast;
/**
* Number of plurals in this rule.
*
* @var int
*/
protected $numPlurals;
/**
* Create a new plural rule.
*
* @param int $numPlurals
* @param array $ast
*/
protected function __construct($numPlurals, array $ast)
{
$this->numPlurals = $numPlurals;
$this->ast = $ast;
}
/**
* Evaluate a number and return the plural index.
*
* @param int $number
* @return int
* @throws Exception\RangeException
*/
public function evaluate($number)
{
$result = $this->evaluateAstPart($this->ast, abs((int) $number));
if ($result < 0 || $result >= $this->numPlurals) {
throw new Exception\RangeException(
sprintf('Calculated result %s is between 0 and %d', $result, ($this->numPlurals - 1))
);
}
return $result;
}
/**
* Get number of possible plural forms.
*
* @return int
*/
public function getNumPlurals()
{
return $this->numPlurals;
}
/**
* Evaluate a part of an ast.
*
* @param array $ast
* @param int $number
* @return int
* @throws Exception\ParseException
*/
protected function evaluateAstPart(array $ast, $number)
{
switch ($ast['id']) {
case 'number':
return $ast['arguments'][0];
case 'n':
return $number;
case '+':
return $this->evaluateAstPart($ast['arguments'][0], $number)
+ $this->evaluateAstPart($ast['arguments'][1], $number);
case '-':
return $this->evaluateAstPart($ast['arguments'][0], $number)
- $this->evaluateAstPart($ast['arguments'][1], $number);
case '/':
// Integer division
return floor(
$this->evaluateAstPart($ast['arguments'][0], $number)
/ $this->evaluateAstPart($ast['arguments'][1], $number)
);
case '*':
return $this->evaluateAstPart($ast['arguments'][0], $number)
* $this->evaluateAstPart($ast['arguments'][1], $number);
case '%':
return $this->evaluateAstPart($ast['arguments'][0], $number)
% $this->evaluateAstPart($ast['arguments'][1], $number);
case '>':
return $this->evaluateAstPart($ast['arguments'][0], $number)
> $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '>=':
return $this->evaluateAstPart($ast['arguments'][0], $number)
>= $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '<':
return $this->evaluateAstPart($ast['arguments'][0], $number)
< $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '<=':
return $this->evaluateAstPart($ast['arguments'][0], $number)
<= $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '==':
return $this->evaluateAstPart($ast['arguments'][0], $number)
== $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '!=':
return $this->evaluateAstPart($ast['arguments'][0], $number)
!= $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '&&':
return $this->evaluateAstPart($ast['arguments'][0], $number)
&& $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '||':
return $this->evaluateAstPart($ast['arguments'][0], $number)
|| $this->evaluateAstPart($ast['arguments'][1], $number)
? 1 : 0;
case '!':
return ! $this->evaluateAstPart($ast['arguments'][0], $number)
? 1 : 0;
case '?':
return $this->evaluateAstPart($ast['arguments'][0], $number)
? $this->evaluateAstPart($ast['arguments'][1], $number)
: $this->evaluateAstPart($ast['arguments'][2], $number);
default:
throw new Exception\ParseException(sprintf(
'Unknown token: %s',
$ast['id']
));
}
}
/**
* Create a new rule from a string.
*
* @param string $string
* @throws Exception\ParseException
* @return Rule
*/
public static function fromString($string)
{
if (static::$parser === null) {
static::$parser = new Parser();
}
if (! preg_match('(nplurals=(?P<nplurals>\d+))', $string, $match)) {
throw new Exception\ParseException(sprintf(
'Unknown or invalid parser rule: %s',
$string
));
}
$numPlurals = (int) $match['nplurals'];
if (! preg_match('(plural=(?P<plural>[^;\n]+))', $string, $match)) {
throw new Exception\ParseException(sprintf(
'Unknown or invalid parser rule: %s',
$string
));
}
$tree = static::$parser->parse($match['plural']);
$ast = static::createAst($tree);
return new static($numPlurals, $ast);
}
/**
* Create an AST from a tree.
*
* Theoretically we could just use the given Symbol, but that one is not
* so easy to serialize and also takes up more memory.
*
* @param Symbol $symbol
* @return array
*/
protected static function createAst(Symbol $symbol)
{
$ast = ['id' => $symbol->id, 'arguments' => []];
switch ($symbol->id) {
case 'n':
break;
case 'number':
$ast['arguments'][] = $symbol->value;
break;
case '!':
$ast['arguments'][] = static::createAst($symbol->first);
break;
case '?':
$ast['arguments'][] = static::createAst($symbol->first);
$ast['arguments'][] = static::createAst($symbol->second);
$ast['arguments'][] = static::createAst($symbol->third);
break;
default:
$ast['arguments'][] = static::createAst($symbol->first);
$ast['arguments'][] = static::createAst($symbol->second);
break;
}
return $ast;
}
}

View File

@ -0,0 +1,159 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Plural;
use Closure;
use Laminas\I18n\Exception;
/**
* Parser symbol.
*
* All properties in the symbol are defined as public for easier and faster
* access from the applied closures. An exception are the closure properties
* themselves, as they have to be accessed via the appropriate getter and
* setter methods.
*/
class Symbol
{
/**
* Parser instance.
*
* @var Parser
*/
public $parser;
/**
* Node or token type name.
*
* @var string
*/
public $id;
/**
* Left binding power (precedence).
*
* @var int
*/
public $leftBindingPower;
/**
* Getter for null denotation.
*
* @var callable
*/
protected $nullDenotationGetter;
/**
* Getter for left denotation.
*
* @var callable
*/
protected $leftDenotationGetter;
/**
* Value used by literals.
*
* @var mixed
*/
public $value;
/**
* First node value.
*
* @var Symbol
*/
public $first;
/**
* Second node value.
*
* @var Symbol
*/
public $second;
/**
* Third node value.
*
* @var Symbol
*/
public $third;
/**
* Create a new symbol.
*
* @param Parser $parser
* @param string $id
* @param int $leftBindingPower
*/
public function __construct(Parser $parser, $id, $leftBindingPower)
{
$this->parser = $parser;
$this->id = $id;
$this->leftBindingPower = $leftBindingPower;
}
/**
* Set the null denotation getter.
*
* @param Closure $getter
* @return $this
*/
public function setNullDenotationGetter(Closure $getter)
{
$this->nullDenotationGetter = $getter;
return $this;
}
/**
* Set the left denotation getter.
*
* @param Closure $getter
* @return $this
*/
public function setLeftDenotationGetter(Closure $getter)
{
$this->leftDenotationGetter = $getter;
return $this;
}
/**
* Get null denotation.
*
* @throws Exception\ParseException
* @return Symbol
*/
public function getNullDenotation()
{
if ($this->nullDenotationGetter === null) {
throw new Exception\ParseException(sprintf('Syntax error: %s', $this->id));
}
/** @var callable $function */
$function = $this->nullDenotationGetter;
return $function($this);
}
/**
* Get left denotation.
*
* @param Symbol $left
* @throws Exception\ParseException
* @return Symbol
*/
public function getLeftDenotation($left)
{
if ($this->leftDenotationGetter === null) {
throw new Exception\ParseException(sprintf('Unknown operator: %s', $this->id));
}
/** @var callable $function */
$function = $this->leftDenotationGetter;
return $function($this, $left);
}
}

View File

@ -0,0 +1,117 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
use ArrayObject;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
/**
* Text domain.
*/
class TextDomain extends ArrayObject
{
/**
* Plural rule.
*
* @var PluralRule
*/
protected $pluralRule;
/**
* Default plural rule shared between instances.
*
* @var PluralRule
*/
protected static $defaultPluralRule;
/**
* Set the plural rule
*
* @param PluralRule $rule
* @return $this
*/
public function setPluralRule(PluralRule $rule)
{
$this->pluralRule = $rule;
return $this;
}
/**
* Get the plural rule.
*
* @param bool $fallbackToDefaultRule
* @return PluralRule|null
*/
public function getPluralRule($fallbackToDefaultRule = true)
{
if ($this->pluralRule === null && $fallbackToDefaultRule) {
return static::getDefaultPluralRule();
}
return $this->pluralRule;
}
/**
* Checks whether the text domain has a plural rule.
*
* @return bool
*/
public function hasPluralRule()
{
return ($this->pluralRule !== null);
}
/**
* Returns a shared default plural rule.
*
* @return PluralRule
*/
public static function getDefaultPluralRule()
{
if (static::$defaultPluralRule === null) {
static::$defaultPluralRule = PluralRule::fromString('nplurals=2; plural=n != 1;');
}
return static::$defaultPluralRule;
}
/**
* Merge another text domain with the current one.
*
* The plural rule of both text domains must be compatible for a successful
* merge. We are only validating the number of plural forms though, as the
* same rule could be made up with different expression.
*
* @param TextDomain $textDomain
* @return $this
* @throws Exception\RuntimeException
*/
public function merge(TextDomain $textDomain)
{
if ($this->hasPluralRule() && $textDomain->hasPluralRule()) {
if ($this->getPluralRule()->getNumPlurals() !== $textDomain->getPluralRule()->getNumPlurals()) {
throw new Exception\RuntimeException(
'Plural rule of merging text domain is not compatible with the current one'
);
}
} elseif ($textDomain->hasPluralRule()) {
$this->setPluralRule($textDomain->getPluralRule());
}
$this->exchangeArray(
array_replace(
$this->getArrayCopy(),
$textDomain->getArrayCopy()
)
);
return $this;
}
}

View File

@ -0,0 +1,837 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
use Laminas\Cache;
use Laminas\Cache\Storage\StorageInterface as CacheStorage;
use Laminas\EventManager\Event;
use Laminas\EventManager\EventManager;
use Laminas\EventManager\EventManagerInterface;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Loader\FileLoaderInterface;
use Laminas\I18n\Translator\Loader\RemoteLoaderInterface;
use Laminas\ServiceManager\ServiceManager;
use Laminas\Stdlib\ArrayUtils;
use Locale;
use Traversable;
/**
* Translator.
*/
class Translator implements TranslatorInterface
{
/**
* Event fired when the translation for a message is missing.
*/
const EVENT_MISSING_TRANSLATION = 'missingTranslation';
/**
* Event fired when no messages were loaded for a locale/text-domain combination.
*/
const EVENT_NO_MESSAGES_LOADED = 'noMessagesLoaded';
/**
* Messages loaded by the translator.
*
* @var array
*/
protected $messages = [];
/**
* Files used for loading messages.
*
* @var array
*/
protected $files = [];
/**
* Patterns used for loading messages.
*
* @var array
*/
protected $patterns = [];
/**
* Remote locations for loading messages.
*
* @var array
*/
protected $remote = [];
/**
* Default locale.
*
* @var string|null
*/
protected $locale;
/**
* Locale to use as fallback if there is no translation.
*
* @var string|null
*/
protected $fallbackLocale;
/**
* Translation cache.
*
* @var CacheStorage|null
*/
protected $cache;
/**
* Plugin manager for translation loaders.
*
* @var LoaderPluginManager
*/
protected $pluginManager;
/**
* Event manager for triggering translator events.
*
* @var EventManagerInterface
*/
protected $events;
/**
* Whether events are enabled
*
* @var bool
*/
protected $eventsEnabled = false;
/**
* Instantiate a translator
*
* @param array|Traversable $options
* @return static
* @throws Exception\InvalidArgumentException
*/
public static function factory($options)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif (! is_array($options)) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects an array or Traversable object; received "%s"',
__METHOD__,
(is_object($options) ? get_class($options) : gettype($options))
));
}
$translator = new static();
// locales
if (isset($options['locale'])) {
$locales = (array) $options['locale'];
$translator->setLocale(array_shift($locales));
if ($locales) {
$translator->setFallbackLocale(array_shift($locales));
}
}
// file patterns
if (isset($options['translation_file_patterns'])) {
if (! is_array($options['translation_file_patterns'])) {
throw new Exception\InvalidArgumentException(
'"translation_file_patterns" should be an array'
);
}
$requiredKeys = ['type', 'base_dir', 'pattern'];
foreach ($options['translation_file_patterns'] as $pattern) {
foreach ($requiredKeys as $key) {
if (! isset($pattern[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for translation pattern options"
);
}
}
$translator->addTranslationFilePattern(
$pattern['type'],
$pattern['base_dir'],
$pattern['pattern'],
isset($pattern['text_domain']) ? $pattern['text_domain'] : 'default'
);
}
}
// files
if (isset($options['translation_files'])) {
if (! is_array($options['translation_files'])) {
throw new Exception\InvalidArgumentException(
'"translation_files" should be an array'
);
}
$requiredKeys = ['type', 'filename'];
foreach ($options['translation_files'] as $file) {
foreach ($requiredKeys as $key) {
if (! isset($file[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for translation file options"
);
}
}
$translator->addTranslationFile(
$file['type'],
$file['filename'],
isset($file['text_domain']) ? $file['text_domain'] : 'default',
isset($file['locale']) ? $file['locale'] : null
);
}
}
// remote
if (isset($options['remote_translation'])) {
if (! is_array($options['remote_translation'])) {
throw new Exception\InvalidArgumentException(
'"remote_translation" should be an array'
);
}
$requiredKeys = ['type'];
foreach ($options['remote_translation'] as $remote) {
foreach ($requiredKeys as $key) {
if (! isset($remote[$key])) {
throw new Exception\InvalidArgumentException(
"'{$key}' is missing for remote translation options"
);
}
}
$translator->addRemoteTranslations(
$remote['type'],
isset($remote['text_domain']) ? $remote['text_domain'] : 'default'
);
}
}
// cache
if (isset($options['cache'])) {
if ($options['cache'] instanceof CacheStorage) {
$translator->setCache($options['cache']);
} else {
$translator->setCache(Cache\StorageFactory::factory($options['cache']));
}
}
// event manager enabled
if (isset($options['event_manager_enabled']) && $options['event_manager_enabled']) {
$translator->enableEventManager();
}
return $translator;
}
/**
* Set the default locale.
*
* @param string|null $locale
* @return $this
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Get the default locale.
*
* @return string
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present and no locale set
*/
public function getLocale()
{
if ($this->locale === null) {
if (! extension_loaded('intl')) {
throw new Exception\ExtensionNotLoadedException(sprintf(
'%s component requires the intl PHP extension',
__NAMESPACE__
));
}
$this->locale = Locale::getDefault();
}
return $this->locale;
}
/**
* Set the fallback locale.
*
* @param string|null $locale
* @return $this
*/
public function setFallbackLocale($locale)
{
$this->fallbackLocale = $locale;
return $this;
}
/**
* Get the fallback locale.
*
* @return string|null
*/
public function getFallbackLocale()
{
return $this->fallbackLocale;
}
/**
* Sets a cache
*
* @param CacheStorage|null $cache
* @return $this
*/
public function setCache(CacheStorage $cache = null)
{
$this->cache = $cache;
return $this;
}
/**
* Returns the set cache
*
* @return CacheStorage|null The set cache
*/
public function getCache()
{
return $this->cache;
}
/**
* Set the plugin manager for translation loaders
*
* @param LoaderPluginManager $pluginManager
* @return $this
*/
public function setPluginManager(LoaderPluginManager $pluginManager)
{
$this->pluginManager = $pluginManager;
return $this;
}
/**
* Retrieve the plugin manager for translation loaders.
*
* Lazy loads an instance if none currently set.
*
* @return LoaderPluginManager
*/
public function getPluginManager()
{
if (! $this->pluginManager instanceof LoaderPluginManager) {
$this->setPluginManager(new LoaderPluginManager(new ServiceManager));
}
return $this->pluginManager;
}
/**
* Translate a message.
*
* @param string $message
* @param string $textDomain
* @param string|null $locale
* @return string
*/
public function translate($message, $textDomain = 'default', $locale = null)
{
$locale = ($locale ?: $this->getLocale());
$translation = $this->getTranslatedMessage($message, $locale, $textDomain);
if ($translation !== null && $translation !== '') {
return $translation;
}
if (null !== ($fallbackLocale = $this->getFallbackLocale())
&& $locale !== $fallbackLocale
) {
return $this->translate($message, $textDomain, $fallbackLocale);
}
return $message;
}
/**
* Translate a plural message.
*
* @param string $singular
* @param string $plural
* @param int $number
* @param string $textDomain
* @param string|null $locale
* @return string
* @throws Exception\OutOfBoundsException
*/
public function translatePlural(
$singular,
$plural,
$number,
$textDomain = 'default',
$locale = null
) {
$locale = $locale ?: $this->getLocale();
$translation = $this->getTranslatedMessage($singular, $locale, $textDomain);
if (is_string($translation)) {
$translation = [$translation];
}
$index = ($number === 1) ? 0 : 1; // en_EN Plural rule
if ($this->messages[$textDomain][$locale] instanceof TextDomain) {
$index = $this->messages[$textDomain][$locale]
->getPluralRule()
->evaluate($number);
}
if (isset($translation[$index]) && $translation[$index] !== '' && $translation[$index] !== null) {
return $translation[$index];
}
if (null !== ($fallbackLocale = $this->getFallbackLocale())
&& $locale !== $fallbackLocale
) {
return $this->translatePlural(
$singular,
$plural,
$number,
$textDomain,
$fallbackLocale
);
}
return $index === 0 ? $singular : $plural;
}
/**
* Get a translated message.
*
* @triggers getTranslatedMessage.missing-translation
* @param string $message
* @param string $locale
* @param string $textDomain
* @return string|null
*/
protected function getTranslatedMessage(
$message,
$locale,
$textDomain = 'default'
) {
if ($message === '' || $message === null) {
return '';
}
if (! isset($this->messages[$textDomain][$locale])) {
$this->loadMessages($textDomain, $locale);
}
if (isset($this->messages[$textDomain][$locale][$message])) {
return $this->messages[$textDomain][$locale][$message];
}
/**
* issue https://github.com/zendframework/zend-i18n/issues/53
*
* storage: array:8 [▼
* "default\x04Welcome" => "Cześć"
* "default\x04Top %s Product" => array:3 [▼
* 0 => "Top %s Produkt"
* 1 => "Top %s Produkty"
* 2 => "Top %s Produktów"
* ]
* "Top %s Products" => ""
* ]
*/
if (isset($this->messages[$textDomain][$locale][$textDomain . "\x04" . $message])) {
return $this->messages[$textDomain][$locale][$textDomain . "\x04" . $message];
}
if ($this->isEventManagerEnabled()) {
$until = static function ($r) {
return is_string($r);
};
$event = new Event(self::EVENT_MISSING_TRANSLATION, $this, [
'message' => $message,
'locale' => $locale,
'text_domain' => $textDomain,
]);
$results = $this->getEventManager()->triggerEventUntil($until, $event);
$last = $results->last();
if (is_string($last)) {
return $last;
}
}
return null;
}
/**
* Add a translation file.
*
* @param string $type
* @param string $filename
* @param string $textDomain
* @param string|null $locale
* @return $this
*/
public function addTranslationFile(
$type,
$filename,
$textDomain = 'default',
$locale = null
) {
$locale = $locale ?: '*';
if (! isset($this->files[$textDomain])) {
$this->files[$textDomain] = [];
}
$this->files[$textDomain][$locale][] = [
'type' => $type,
'filename' => $filename,
];
return $this;
}
/**
* Add multiple translations with a file pattern.
*
* @param string $type
* @param string $baseDir
* @param string $pattern
* @param string $textDomain
* @return $this
*/
public function addTranslationFilePattern(
$type,
$baseDir,
$pattern,
$textDomain = 'default'
) {
if (! isset($this->patterns[$textDomain])) {
$this->patterns[$textDomain] = [];
}
$this->patterns[$textDomain][] = [
'type' => $type,
'baseDir' => rtrim($baseDir, '/'),
'pattern' => $pattern,
];
return $this;
}
/**
* Add remote translations.
*
* @param string $type
* @param string $textDomain
* @return $this
*/
public function addRemoteTranslations($type, $textDomain = 'default')
{
if (! isset($this->remote[$textDomain])) {
$this->remote[$textDomain] = [];
}
$this->remote[$textDomain][] = $type;
return $this;
}
/**
* Get the cache identifier for a specific textDomain and locale.
*
* @param string $textDomain
* @param string $locale
* @return string
*/
public function getCacheId($textDomain, $locale)
{
return 'Laminas_I18n_Translator_Messages_' . md5($textDomain . $locale);
}
/**
* Clears the cache for a specific textDomain and locale.
*
* @param string $textDomain
* @param string $locale
* @return bool
*/
public function clearCache($textDomain, $locale)
{
if (null === ($cache = $this->getCache())) {
return false;
}
return $cache->removeItem($this->getCacheId($textDomain, $locale));
}
/**
* Load messages for a given language and domain.
*
* @triggers loadMessages.no-messages-loaded
* @param string $textDomain
* @param string $locale
* @throws Exception\RuntimeException
* @return void
*/
protected function loadMessages($textDomain, $locale)
{
if (! isset($this->messages[$textDomain])) {
$this->messages[$textDomain] = [];
}
if (null !== ($cache = $this->getCache())) {
$cacheId = $this->getCacheId($textDomain, $locale);
if (null !== ($result = $cache->getItem($cacheId))) {
$this->messages[$textDomain][$locale] = $result;
return;
}
}
$messagesLoaded = false;
$messagesLoaded |= $this->loadMessagesFromRemote($textDomain, $locale);
$messagesLoaded |= $this->loadMessagesFromPatterns($textDomain, $locale);
$messagesLoaded |= $this->loadMessagesFromFiles($textDomain, $locale);
if (! $messagesLoaded) {
$discoveredTextDomain = null;
if ($this->isEventManagerEnabled()) {
$until = static function ($r) {
return ($r instanceof TextDomain);
};
$event = new Event(self::EVENT_NO_MESSAGES_LOADED, $this, [
'locale' => $locale,
'text_domain' => $textDomain,
]);
$results = $this->getEventManager()->triggerEventUntil($until, $event);
$last = $results->last();
if ($last instanceof TextDomain) {
$discoveredTextDomain = $last;
}
}
$this->messages[$textDomain][$locale] = $discoveredTextDomain;
$messagesLoaded = true;
}
if ($messagesLoaded && $cache !== null) {
$cache->setItem($cacheId, $this->messages[$textDomain][$locale]);
}
}
/**
* Load messages from remote sources.
*
* @param string $textDomain
* @param string $locale
* @return bool
* @throws Exception\RuntimeException When specified loader is not a remote loader
*/
protected function loadMessagesFromRemote($textDomain, $locale)
{
$messagesLoaded = false;
if (isset($this->remote[$textDomain])) {
foreach ($this->remote[$textDomain] as $loaderType) {
$loader = $this->getPluginManager()->get($loaderType);
if (! $loader instanceof RemoteLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a remote loader');
}
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->merge($loader->load($locale, $textDomain));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $textDomain);
}
$messagesLoaded = true;
}
}
return $messagesLoaded;
}
/**
* Load messages from patterns.
*
* @param string $textDomain
* @param string $locale
* @return bool
* @throws Exception\RuntimeException When specified loader is not a file loader
*/
protected function loadMessagesFromPatterns($textDomain, $locale)
{
$messagesLoaded = false;
if (isset($this->patterns[$textDomain])) {
foreach ($this->patterns[$textDomain] as $pattern) {
$filename = $pattern['baseDir'] . '/' . sprintf($pattern['pattern'], $locale);
if (is_file($filename)) {
$loader = $this->getPluginManager()->get($pattern['type']);
if (! $loader instanceof FileLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a file loader');
}
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->merge($loader->load($locale, $filename));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $filename);
}
$messagesLoaded = true;
}
}
}
return $messagesLoaded;
}
/**
* Load messages from files.
*
* @param string $textDomain
* @param string $locale
* @return bool
* @throws Exception\RuntimeException When specified loader is not a file loader
*/
protected function loadMessagesFromFiles($textDomain, $locale)
{
$messagesLoaded = false;
foreach ([$locale, '*'] as $currentLocale) {
if (! isset($this->files[$textDomain][$currentLocale])) {
continue;
}
foreach ($this->files[$textDomain][$currentLocale] as $file) {
$loader = $this->getPluginManager()->get($file['type']);
if (! $loader instanceof FileLoaderInterface) {
throw new Exception\RuntimeException('Specified loader is not a file loader');
}
if (isset($this->messages[$textDomain][$locale])) {
$this->messages[$textDomain][$locale]->merge($loader->load($locale, $file['filename']));
} else {
$this->messages[$textDomain][$locale] = $loader->load($locale, $file['filename']);
}
$messagesLoaded = true;
}
unset($this->files[$textDomain][$currentLocale]);
}
return $messagesLoaded;
}
/**
* Return all the messages.
*
* @param string $textDomain
* @param string|null $locale
* @return mixed
*/
public function getAllMessages($textDomain = 'default', $locale = null)
{
$locale = $locale ?: $this->getLocale();
if (! isset($this->messages[$textDomain][$locale])) {
$this->loadMessages($textDomain, $locale);
}
return $this->messages[$textDomain][$locale];
}
/**
* Get the event manager.
*
* @return EventManagerInterface
*/
public function getEventManager()
{
if (! $this->events instanceof EventManagerInterface) {
$this->setEventManager(new EventManager());
}
return $this->events;
}
/**
* Set the event manager instance used by this translator.
*
* @param EventManagerInterface $events
* @return $this
*/
public function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers([
__CLASS__,
get_class($this),
'translator',
]);
$this->events = $events;
return $this;
}
/**
* Check whether the event manager is enabled.
*
* @return bool
*/
public function isEventManagerEnabled()
{
return $this->eventsEnabled;
}
/**
* Enable the event manager.
*
* @return $this
*/
public function enableEventManager()
{
$this->eventsEnabled = true;
return $this;
}
/**
* Disable the event manager.
*
* @return $this
*/
public function disableEventManager()
{
$this->eventsEnabled = false;
return $this;
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
interface TranslatorAwareInterface
{
/**
* Sets translator to use in helper
*
* @param TranslatorInterface|null $translator Default is null, which sets no translator.
* @param string|null $textDomain Default is null, which skips setTranslatorTextDomain
* @return $this
*/
public function setTranslator(TranslatorInterface $translator = null, $textDomain = null);
/**
* Returns translator used in object
*
* @return TranslatorInterface|null
*/
public function getTranslator();
/**
* Checks if the object has a translator
*
* @return bool
*/
public function hasTranslator();
/**
* Sets whether translator is enabled and should be used
*
* @param bool $enabled [optional] whether translator should be used.
* Default is true.
* @return $this
*/
public function setTranslatorEnabled($enabled = true);
/**
* Returns whether translator is enabled and should be used
*
* @return bool
*/
public function isTranslatorEnabled();
/**
* Set translation text domain
*
* @param string $textDomain
* @return $this
*/
public function setTranslatorTextDomain($textDomain = 'default');
/**
* Return the translation text domain
*
* @return string
*/
public function getTranslatorTextDomain();
}

View File

@ -0,0 +1,111 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
trait TranslatorAwareTrait
{
/**
* @var TranslatorInterface|null
*/
protected $translator;
/**
* @var bool
*/
protected $translatorEnabled = true;
/**
* @var string
*/
protected $translatorTextDomain = 'default';
/**
* Sets translator to use in helper
*
* @param TranslatorInterface|null $translator
* @param string|null $textDomain
* @return $this
*/
public function setTranslator(TranslatorInterface $translator = null, $textDomain = null)
{
$this->translator = $translator;
if (null !== $textDomain) {
$this->setTranslatorTextDomain($textDomain);
}
return $this;
}
/**
* Returns translator used in object
*
* @return TranslatorInterface|null
*/
public function getTranslator()
{
return $this->translator;
}
/**
* Checks if the object has a translator
*
* @return bool
*/
public function hasTranslator()
{
return (null !== $this->translator);
}
/**
* Sets whether translator is enabled and should be used
*
* @param bool $enabled
* @return $this
*/
public function setTranslatorEnabled($enabled = true)
{
$this->translatorEnabled = $enabled;
return $this;
}
/**
* Returns whether translator is enabled and should be used
*
* @return bool
*/
public function isTranslatorEnabled()
{
return $this->translatorEnabled;
}
/**
* Set translation text domain
*
* @param string $textDomain
* @return $this
*/
public function setTranslatorTextDomain($textDomain = 'default')
{
$this->translatorTextDomain = $textDomain;
return $this;
}
/**
* Return the translation text domain
*
* @return string
*/
public function getTranslatorTextDomain()
{
return $this->translatorTextDomain;
}
}

View File

@ -0,0 +1,43 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
/**
* Translator interface.
*/
interface TranslatorInterface
{
/**
* Translate a message.
*
* @param string $message
* @param string $textDomain
* @param string $locale
* @return string
*/
public function translate($message, $textDomain = 'default', $locale = null);
/**
* Translate a plural message.
*
* @param string $singular
* @param string $plural
* @param int $number
* @param string $textDomain
* @param string|null $locale
* @return string
*/
public function translatePlural(
$singular,
$plural,
$number,
$textDomain = 'default',
$locale = null
);
}

View File

@ -0,0 +1,52 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\FactoryInterface;
use Laminas\ServiceManager\ServiceLocatorInterface;
/**
* Translator.
*/
class TranslatorServiceFactory implements FactoryInterface
{
/**
* Create a Translator instance.
*
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return Translator
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// Configure the translator
$config = $container->get('config');
$trConfig = isset($config['translator']) ? $config['translator'] : [];
$translator = Translator::factory($trConfig);
if ($container->has('TranslatorPluginManager')) {
$translator->setPluginManager($container->get('TranslatorPluginManager'));
}
return $translator;
}
/**
* laminas-servicemanager v2 factory for creating Translator instance.
*
* Proxies to `__invoke()`.
*
* @param ServiceLocatorInterface $serviceLocator
* @return Translator
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return $this($serviceLocator, Translator::class);
}
}

View File

@ -0,0 +1,116 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use Laminas\I18n\Filter\Alnum as AlnumFilter;
use Laminas\Validator\AbstractValidator;
class Alnum extends AbstractValidator
{
const INVALID = 'alnumInvalid';
const NOT_ALNUM = 'notAlnum';
const STRING_EMPTY = 'alnumStringEmpty';
/**
* Alphanumeric filter used for validation
*
* @var AlnumFilter
*/
protected static $filter;
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String, integer or float expected',
self::NOT_ALNUM => 'The input contains characters which are non alphabetic and no digits',
self::STRING_EMPTY => 'The input is an empty string',
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'allowWhiteSpace' => false, // Whether to allow white space characters; off by default
];
/**
* Sets default option values for this instance
*
* @param array|bool $allowWhiteSpace
*/
public function __construct($allowWhiteSpace = false)
{
$options = is_array($allowWhiteSpace) ? $allowWhiteSpace : null;
parent::__construct($options);
if (is_scalar($allowWhiteSpace)) {
$this->options['allowWhiteSpace'] = (bool) $allowWhiteSpace;
}
}
/**
* Returns the allowWhiteSpace option
*
* @return bool
*/
public function getAllowWhiteSpace()
{
return $this->options['allowWhiteSpace'];
}
/**
* Sets the allowWhiteSpace option
*
* @param bool $allowWhiteSpace
* @return $this
*/
public function setAllowWhiteSpace($allowWhiteSpace)
{
$this->options['allowWhiteSpace'] = (bool) $allowWhiteSpace;
return $this;
}
/**
* Returns true if and only if $value contains only alphabetic and digit characters
*
* @param int|float|string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value) && ! is_float($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if ('' === $value) {
$this->error(self::STRING_EMPTY);
return false;
}
if (null === static::$filter) {
static::$filter = new AlnumFilter();
}
static::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']);
if ($value != static::$filter->filter($value)) {
$this->error(self::NOT_ALNUM);
return false;
}
return true;
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use Laminas\I18n\Filter\Alpha as AlphaFilter;
class Alpha extends Alnum
{
const INVALID = 'alphaInvalid';
const NOT_ALPHA = 'notAlpha';
const STRING_EMPTY = 'alphaStringEmpty';
/**
* Alphabetic filter used for validation
*
* @var AlphaFilter
*/
protected static $filter;
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::NOT_ALPHA => 'The input contains non alphabetic characters',
self::STRING_EMPTY => 'The input is an empty string'
];
/**
* Options for this validator
*
* @var array
*/
protected $options = [
'allowWhiteSpace' => false, // Whether to allow white space characters; off by default
];
/**
* Returns true if and only if $value contains only alphabetic characters
*
* @param string $value
* @return bool
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if ('' === $value) {
$this->error(self::STRING_EMPTY);
return false;
}
if (null === static::$filter) {
static::$filter = new AlphaFilter();
}
//static::$filter->setAllowWhiteSpace($this->allowWhiteSpace);
static::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']);
if ($value !== static::$filter->filter($value)) {
$this->error(self::NOT_ALPHA);
return false;
}
return true;
}
}

View File

@ -0,0 +1,335 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use IntlDateFormatter;
use IntlException;
use Laminas\I18n\Exception as I18nException;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception as ValidatorException;
use Locale;
use Traversable;
class DateTime extends AbstractValidator
{
const INVALID = 'datetimeInvalid';
const INVALID_DATETIME = 'datetimeInvalidDateTime';
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String expected',
self::INVALID_DATETIME => 'The input does not appear to be a valid datetime',
];
/**
* Optional locale
*
* @var string|null
*/
protected $locale;
/**
* @var int|null
*/
protected $dateType;
/**
* @var int|null
*/
protected $timeType;
/**
* Optional timezone
*
* @var string|null
*/
protected $timezone;
/**
* @var string|null
*/
protected $pattern;
/**
* @var int|null
*/
protected $calendar;
/**
* @var IntlDateFormatter
*/
protected $formatter;
/**
* Is the formatter invalidated
* Invalidation occurs when immutable properties are changed
*
* @var bool
*/
protected $invalidateFormatter = false;
/**
* Constructor for the Date validator
*
* @param array|Traversable $options
* @throws I18nException\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct($options = [])
{
if (! extension_loaded('intl')) {
throw new I18nException\ExtensionNotLoadedException(
sprintf('%s component requires the intl PHP extension', __NAMESPACE__)
);
}
// Delaying initialization until we know ext/intl is available
$this->dateType = IntlDateFormatter::NONE;
$this->timeType = IntlDateFormatter::NONE;
$this->calendar = IntlDateFormatter::GREGORIAN;
parent::__construct($options);
if (null === $this->locale) {
$this->locale = Locale::getDefault();
}
if (null === $this->timezone) {
$this->timezone = date_default_timezone_get();
}
}
/**
* Sets the calendar to be used by the IntlDateFormatter
*
* @param int|null $calendar
* @return $this
*/
public function setCalendar($calendar)
{
$this->calendar = $calendar;
return $this;
}
/**
* Returns the calendar to by the IntlDateFormatter
*
* @return int|null
*/
public function getCalendar()
{
if ($this->formatter && ! $this->invalidateFormatter) {
return $this->getIntlDateFormatter()->getCalendar();
}
return $this->calendar;
}
/**
* Sets the date format to be used by the IntlDateFormatter
*
* @param int|null $dateType
* @return $this
*/
public function setDateType($dateType)
{
$this->dateType = $dateType;
$this->invalidateFormatter = true;
return $this;
}
/**
* Returns the date format used by the IntlDateFormatter
*
* @return int|null
*/
public function getDateType()
{
return $this->dateType;
}
/**
* Sets the pattern to be used by the IntlDateFormatter
*
* @param string|null $pattern
* @return $this
*/
public function setPattern($pattern)
{
$this->pattern = $pattern;
return $this;
}
/**
* Returns the pattern used by the IntlDateFormatter
*
* @return string|null
*/
public function getPattern()
{
if ($this->formatter && ! $this->invalidateFormatter) {
return $this->getIntlDateFormatter()->getPattern();
}
return $this->pattern;
}
/**
* Sets the time format to be used by the IntlDateFormatter
*
* @param int|null $timeType
* @return $this
*/
public function setTimeType($timeType)
{
$this->timeType = $timeType;
$this->invalidateFormatter = true;
return $this;
}
/**
* Returns the time format used by the IntlDateFormatter
*
* @return int|null
*/
public function getTimeType()
{
return $this->timeType;
}
/**
* Sets the timezone to be used by the IntlDateFormatter
*
* @param string|null $timezone
* @return $this
*/
public function setTimezone($timezone)
{
$this->timezone = $timezone;
return $this;
}
/**
* Returns the timezone used by the IntlDateFormatter or the system default if none given
*
* @return string|null
*/
public function getTimezone()
{
if ($this->formatter && ! $this->invalidateFormatter) {
return $this->getIntlDateFormatter()->getTimeZoneId();
}
return $this->timezone;
}
/**
* Sets the locale to be used by the IntlDateFormatter
*
* @param string|null $locale
* @return $this
*/
public function setLocale($locale)
{
$this->locale = $locale;
$this->invalidateFormatter = true;
return $this;
}
/**
* Returns the locale used by the IntlDateFormatter or the system default if none given
*
* @return string|null
*/
public function getLocale()
{
return $this->locale;
}
/**
* Returns true if and only if $value is a floating-point value
*
* @param string $value
* @return bool
* @throws ValidatorException\InvalidArgumentException
*/
public function isValid($value)
{
if (! is_string($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
try {
$formatter = $this->getIntlDateFormatter();
if (intl_is_failure($formatter->getErrorCode())) {
throw new ValidatorException\InvalidArgumentException($formatter->getErrorMessage());
}
} catch (IntlException $intlException) {
throw new ValidatorException\InvalidArgumentException($intlException->getMessage(), 0, $intlException);
}
try {
$timestamp = $formatter->parse($value);
if (intl_is_failure($formatter->getErrorCode()) || $timestamp === false) {
$this->error(self::INVALID_DATETIME);
$this->invalidateFormatter = true;
return false;
}
} catch (IntlException $intlException) {
$this->error(self::INVALID_DATETIME);
$this->invalidateFormatter = true;
return false;
}
return true;
}
/**
* Returns a non lenient configured IntlDateFormatter
*
* @return IntlDateFormatter
*/
protected function getIntlDateFormatter()
{
if ($this->formatter === null || $this->invalidateFormatter) {
$this->formatter = new IntlDateFormatter(
$this->getLocale(),
$this->getDateType(),
$this->getTimeType(),
$this->timezone,
$this->calendar,
$this->pattern
);
$this->formatter->setLenient(false);
$this->setTimezone($this->formatter->getTimezone());
$this->setCalendar($this->formatter->getCalendar());
$this->setPattern($this->formatter->getPattern());
$this->invalidateFormatter = false;
}
return $this->formatter;
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use Laminas\I18n\Exception;
use Traversable;
/**
* Stub class for backwards compatibility.
*
* Since PHP 7 adds "float" as a reserved keyword, we can no longer have a class
* named that and retain PHP 7 compatibility. The original class has been
* renamed to "IsFloat", and this class is now an extension of it. It raises an
* E_USER_DEPRECATED to warn users to migrate.
*
* @deprecated
*/
class Float extends IsFloat
{
/**
* Constructor for the integer validator
*
* @param array|Traversable $options
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct($options = [])
{
trigger_error(
sprintf(
'The class %s has been deprecated; please use %s\\IsFloat',
__CLASS__,
__NAMESPACE__
),
E_USER_DEPRECATED
);
parent::__construct($options);
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use Laminas\I18n\Exception;
use Traversable;
/**
* Stub class for backwards compatibility.
*
* Since PHP 7 adds "int" as a reserved keyword, we can no longer have a class
* named that and retain PHP 7 compatibility. The original class has been
* renamed to "IsInt", and this class is now an extension of it. It raises an
* E_USER_DEPRECATED to warn users to migrate.
*
* @deprecated
*/
class Int extends IsInt
{
/**
* Constructor for the integer validator
*
* @param array|Traversable $options
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct($options = [])
{
trigger_error(
sprintf(
'The class %s has been deprecated; please use %s\\IsInt',
__CLASS__,
__NAMESPACE__
),
E_USER_DEPRECATED
);
parent::__construct($options);
}
}

View File

@ -0,0 +1,252 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use IntlException;
use Laminas\I18n\Exception as I18nException;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Stdlib\StringUtils;
use Laminas\Stdlib\StringWrapper\StringWrapperInterface;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Locale;
use NumberFormatter;
use Traversable;
class IsFloat extends AbstractValidator
{
const INVALID = 'floatInvalid';
const NOT_FLOAT = 'notFloat';
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String, integer or float expected',
self::NOT_FLOAT => 'The input does not appear to be a float',
];
/**
* Optional locale
*
* @var string|null
*/
protected $locale;
/**
* UTF-8 compatible wrapper for string functions
*
* @var StringWrapperInterface
*/
protected $wrapper;
/**
* Constructor for the integer validator
*
* @param array|Traversable $options
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct($options = [])
{
if (! extension_loaded('intl')) {
throw new I18nException\ExtensionNotLoadedException(
sprintf('%s component requires the intl PHP extension', __NAMESPACE__)
);
}
$this->wrapper = StringUtils::getWrapper();
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (isset($options['locale'])) {
$this->setLocale($options['locale']);
}
parent::__construct($options);
}
/**
* Returns the set locale
*
* @return string
*/
public function getLocale()
{
if (null === $this->locale) {
$this->locale = Locale::getDefault();
}
return $this->locale;
}
/**
* Sets the locale to use
*
* @param string|null $locale
* @return $this
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Returns true if and only if $value is a floating-point value. Uses the formal definition of a float as described
* in the PHP manual: {@link https://www.php.net/float}
*
* @param float|int|string $value
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function isValid($value)
{
if (! is_scalar($value) || is_bool($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
if (is_float($value) || is_int($value)) {
return true;
}
// Need to check if this is scientific formatted string. If not, switch to decimal.
$formatter = new NumberFormatter($this->getLocale(), NumberFormatter::SCIENTIFIC);
try {
if (intl_is_failure($formatter->getErrorCode())) {
throw new Exception\InvalidArgumentException($formatter->getErrorMessage());
}
} catch (IntlException $intlException) {
throw new Exception\InvalidArgumentException($intlException->getMessage(), 0, $intlException);
}
if (StringUtils::hasPcreUnicodeSupport()) {
$exponentialSymbols = '[Ee' . $formatter->getSymbol(NumberFormatter::EXPONENTIAL_SYMBOL) . ']+';
$search = '/' . $exponentialSymbols . '/u';
} else {
$exponentialSymbols = '[Ee]';
$search = '/' . $exponentialSymbols . '/';
}
if (! preg_match($search, $value)) {
$formatter = new NumberFormatter($this->getLocale(), NumberFormatter::DECIMAL);
}
/**
* @desc There are separator "look-alikes" for decimal and group separators that are more commonly used than the
* official unicode character. We need to replace those with the real thing - or remove it.
*/
$groupSeparator = $formatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
$decSeparator = $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
//NO-BREAK SPACE and ARABIC THOUSANDS SEPARATOR
if ($groupSeparator === "\xC2\xA0") {
$value = str_replace(' ', $groupSeparator, $value);
} elseif ($groupSeparator === "\xD9\xAC") {
//NumberFormatter doesn't have grouping at all for Arabic-Indic
$value = str_replace(['\'', $groupSeparator], '', $value);
}
//ARABIC DECIMAL SEPARATOR
if ($decSeparator === "\xD9\xAB") {
$value = str_replace(',', $decSeparator, $value);
}
$groupSeparatorPosition = $this->wrapper->strpos($value, $groupSeparator);
$decSeparatorPosition = $this->wrapper->strpos($value, $decSeparator);
//We have separators, and they are flipped. i.e. 2.000,000 for en-US
if ($groupSeparatorPosition && $decSeparatorPosition && $groupSeparatorPosition > $decSeparatorPosition) {
$this->error(self::NOT_FLOAT);
return false;
}
//If we have Unicode support, we can use the real graphemes, otherwise, just the ASCII characters
$decimal = '['. preg_quote($decSeparator, '/') . ']';
$prefix = '[+-]';
$exp = $exponentialSymbols;
$numberRange = '0-9';
$useUnicode = '';
$suffix = '';
if (StringUtils::hasPcreUnicodeSupport()) {
$prefix = '['
. preg_quote(
$formatter->getTextAttribute(NumberFormatter::POSITIVE_PREFIX)
. $formatter->getTextAttribute(NumberFormatter::NEGATIVE_PREFIX)
. $formatter->getSymbol(NumberFormatter::PLUS_SIGN_SYMBOL)
. $formatter->getSymbol(NumberFormatter::MINUS_SIGN_SYMBOL),
'/'
)
. ']{0,3}';
$suffix = ($formatter->getTextAttribute(NumberFormatter::NEGATIVE_SUFFIX))
? '['
. preg_quote(
$formatter->getTextAttribute(NumberFormatter::POSITIVE_SUFFIX)
. $formatter->getTextAttribute(NumberFormatter::NEGATIVE_SUFFIX)
. $formatter->getSymbol(NumberFormatter::PLUS_SIGN_SYMBOL)
. $formatter->getSymbol(NumberFormatter::MINUS_SIGN_SYMBOL),
'/'
)
. ']{0,3}'
: '';
$numberRange = '\p{N}';
$useUnicode = 'u';
}
/**
* @desc Match against the formal definition of a float. The
* exponential number check is modified for RTL non-Latin number
* systems (Arabic-Indic numbering). I'm also switching out the period
* for the decimal separator. The formal definition leaves out +- from
* the integer and decimal notations so add that. This also checks
* that a grouping sperator is not in the last GROUPING_SIZE graphemes
* of the string - i.e. 10,6 is not valid for en-US.
* @see https://www.php.net/float
*/
$lnum = '[' . $numberRange . ']+';
$dnum = '(([' . $numberRange . ']*' . $decimal . $lnum . ')|('
. $lnum . $decimal . '[' . $numberRange . ']*))';
$expDnum = '((' . $prefix . '((' . $lnum . '|' . $dnum . ')' . $exp . $prefix . $lnum . ')' . $suffix . ')|'
. '(' . $suffix . '(' . $lnum . $prefix . $exp . '(' . $dnum . '|' . $lnum . '))' . $prefix . '))';
// LEFT-TO-RIGHT MARK (U+200E) is messing up everything for the handful
// of locales that have it
$lnumSearch = str_replace("\xE2\x80\x8E", '', '/^' .$prefix . $lnum . $suffix . '$/' . $useUnicode);
$dnumSearch = str_replace("\xE2\x80\x8E", '', '/^' .$prefix . $dnum . $suffix . '$/' . $useUnicode);
$expDnumSearch = str_replace("\xE2\x80\x8E", '', '/^' . $expDnum . '$/' . $useUnicode);
$value = str_replace("\xE2\x80\x8E", '', $value);
$unGroupedValue = str_replace($groupSeparator, '', $value);
// No strrpos() in wrappers yet. ICU 4.x doesn't have grouping size for
// everything. ICU 52 has 3 for ALL locales.
$groupSize = $formatter->getAttribute(NumberFormatter::GROUPING_SIZE) ?: 3;
$lastStringGroup = $this->wrapper->substr($value, -$groupSize);
if ((preg_match($lnumSearch, $unGroupedValue)
|| preg_match($dnumSearch, $unGroupedValue)
|| preg_match($expDnumSearch, $unGroupedValue))
&& false === $this->wrapper->strpos($lastStringGroup, $groupSeparator)
) {
return true;
}
$this->error(self::NOT_FLOAT);
return false;
}
}

View File

@ -0,0 +1,195 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use IntlException;
use Laminas\I18n\Exception as I18nException;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Validator\AbstractValidator;
use Laminas\Validator\Exception;
use Locale;
use NumberFormatter;
use Traversable;
class IsInt extends AbstractValidator
{
const INVALID = 'intInvalid';
const NOT_INT = 'notInt';
const NOT_INT_STRICT = 'notIntStrict';
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::INVALID => 'Invalid type given. String or integer expected',
self::NOT_INT => 'The input does not appear to be an integer',
self::NOT_INT_STRICT => 'The input is not strictly an integer',
];
/**
* Optional locale
*
* @var string|null
*/
protected $locale;
/**
* Data type is not enforced by default, so the string '123' is considered an integer.
* Setting strict to true will enforce the integer data type.
*
* @var bool
*/
protected $strict = false;
/**
* Constructor for the integer validator
*
* @param array|Traversable $options
* @throws Exception\ExtensionNotLoadedException if ext/intl is not present
*/
public function __construct($options = [])
{
if (! extension_loaded('intl')) {
throw new I18nException\ExtensionNotLoadedException(sprintf(
'%s component requires the intl PHP extension',
__NAMESPACE__
));
}
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (isset($options['locale'])) {
$this->setLocale($options['locale']);
}
if (array_key_exists('strict', $options)) {
$this->setStrict($options['strict']);
}
parent::__construct($options);
}
/**
* Returns the set locale
*
* @return string|null
*/
public function getLocale()
{
if (null === $this->locale) {
$this->locale = Locale::getDefault();
}
return $this->locale;
}
/**
* Sets the locale to use
*
* @param string|null $locale
* @return $this
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Returns the strict option
*
* @return bool
*/
public function getStrict()
{
return $this->strict;
}
/**
* Sets the strict option mode
*
* @param bool $strict
* @return $this
* @throws Exception\InvalidArgumentException
*/
public function setStrict($strict)
{
if (! is_bool($strict)) {
throw new Exception\InvalidArgumentException('Strict option must be a boolean');
}
$this->strict = $strict;
return $this;
}
/**
* Returns true if and only if $value is a valid integer
*
* @param string|int|float $value
* @return bool
* @throws Exception\InvalidArgumentException
*/
public function isValid($value)
{
if (! is_string($value) && ! is_int($value) && ! is_float($value)) {
$this->error(self::INVALID);
return false;
}
if (is_int($value)) {
return true;
}
if ($this->strict) {
$this->error(self::NOT_INT_STRICT);
return false;
}
$this->setValue($value);
$locale = $this->getLocale();
try {
$format = new NumberFormatter($locale, NumberFormatter::DECIMAL);
if (intl_is_failure($format->getErrorCode())) {
throw new Exception\InvalidArgumentException('Invalid locale string given');
}
} catch (IntlException $intlException) {
throw new Exception\InvalidArgumentException('Invalid locale string given', 0, $intlException);
}
try {
$parsedInt = $format->parse($value, NumberFormatter::TYPE_INT64);
if (intl_is_failure($format->getErrorCode())) {
$this->error(self::NOT_INT);
return false;
}
} catch (IntlException $intlException) {
$this->error(self::NOT_INT);
return false;
}
$decimalSep = $format->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
$groupingSep = $format->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
$valueFiltered = strtr($value, [
$groupingSep => '',
$decimalSep => '.',
]);
if ((string) $parsedInt !== $valueFiltered) {
$this->error(self::NOT_INT);
return false;
}
return true;
}
}

View File

@ -0,0 +1,267 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Validator;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Validator\AbstractValidator;
use Locale;
use Traversable;
class PhoneNumber extends AbstractValidator
{
const NO_MATCH = 'phoneNumberNoMatch';
const UNSUPPORTED = 'phoneNumberUnsupported';
const INVALID = 'phoneNumberInvalid';
/**
* Validation failure message template definitions
*
* @var string[]
*/
protected $messageTemplates = [
self::NO_MATCH => 'The input does not match a phone number format',
self::UNSUPPORTED => 'The country provided is currently unsupported',
self::INVALID => 'Invalid type given. String expected',
];
/**
* Phone Number Patterns
*
* @link http://code.google.com/p/libphonenumber/source/browse/trunk/resources/PhoneNumberMetadata.xml
* @var array
*/
protected static $phone = [];
/**
* ISO 3611 Country Code
*
* @var string
*/
protected $country;
/**
* Allow Possible Matches
*
* @var bool
*/
protected $allowPossible = false;
/**
* Allowed Types
*
* @var string[]
*/
protected $allowedTypes = [
'general',
'fixed',
'tollfree',
'personal',
'mobile',
'voip',
'uan',
];
/**
* Constructor for the PhoneNumber validator
*
* Options
* - country | string | field or value
* - allowed_types | array | array of allowed types
* - allow_possible | boolean | allow possible matches aka non-strict
*
* @param array|Traversable $options
*/
public function __construct($options = [])
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (array_key_exists('country', $options)) {
$this->setCountry($options['country']);
} else {
$country = Locale::getRegion(Locale::getDefault());
$this->setCountry($country);
}
if (isset($options['allowed_types'])) {
$this->allowedTypes($options['allowed_types']);
}
if (isset($options['allow_possible'])) {
$this->allowPossible($options['allow_possible']);
}
parent::__construct($options);
}
/**
* Allowed Types
*
* @param string[]|null $types
* @return $this|string[]
*/
public function allowedTypes(array $types = null)
{
if (null !== $types) {
$this->allowedTypes = $types;
return $this;
}
return $this->allowedTypes;
}
/**
* Allow Possible
*
* @param bool|null $possible
* @return $this|bool
*/
public function allowPossible($possible = null)
{
if (null !== $possible) {
$this->allowPossible = (bool) $possible;
return $this;
}
return $this->allowPossible;
}
/**
* Get Country
*
* @return string
*/
public function getCountry()
{
return $this->country;
}
/**
* Set Country
*
* @param string $country
* @return $this
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
/**
* Load Pattern
*
* @param string $code
* @return array[]|false
*/
protected function loadPattern($code)
{
if (! isset(static::$phone[$code])) {
if (! preg_match('/^[A-Z]{2}$/D', $code)) {
return false;
}
$file = __DIR__ . '/PhoneNumber/' . $code . '.php';
if (! file_exists($file)) {
return false;
}
static::$phone[$code] = include $file;
}
return static::$phone[$code];
}
/**
* Returns true if and only if $value matches phone number format
*
* @param string|null $value
* @param array|null $context
* @return bool
*/
public function isValid($value = null, $context = null)
{
if (! is_scalar($value)) {
$this->error(self::INVALID);
return false;
}
$this->setValue($value);
$country = $this->getCountry();
if (! $countryPattern = $this->loadPattern(strtoupper($country))) {
if (isset($context[$country])) {
$country = $context[$country];
}
if (! $countryPattern = $this->loadPattern(strtoupper($country))) {
$this->error(self::UNSUPPORTED);
return false;
}
}
$codeLength = strlen($countryPattern['code']);
/*
* Check for existence of either:
* 1) E.123/E.164 international prefix
* 2) International double-O prefix
* 3) Bare country prefix
*/
if (0 === strpos($value, '+' . $countryPattern['code'])) {
$valueNoCountry = substr($value, $codeLength + 1);
} elseif (0 === strpos($value, '00' . $countryPattern['code'])) {
$valueNoCountry = substr($value, $codeLength + 2);
} elseif (0 === strpos($value, $countryPattern['code'])) {
$valueNoCountry = substr($value, $codeLength);
}
// check against allowed types strict match:
foreach ($countryPattern['patterns']['national'] as $type => $pattern) {
if (in_array($type, $this->allowedTypes, true)) {
// check pattern:
if (preg_match($pattern, $value)) {
return true;
}
if (isset($valueNoCountry) && preg_match($pattern, $valueNoCountry)) {
// this handles conditions where the country code and prefix are the same
return true;
}
}
}
// check for possible match:
if ($this->allowPossible()) {
foreach ($countryPattern['patterns']['possible'] as $type => $pattern) {
if (in_array($type, $this->allowedTypes, true)) {
// check pattern:
if (preg_match($pattern, $value)) {
return true;
}
if (isset($valueNoCountry) && preg_match($pattern, $valueNoCountry)) {
// this handles conditions where the country code and prefix are the same
return true;
}
}
}
}
$this->error(self::NO_MATCH);
return false;
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '247',
'patterns' => [
'national' => [
'general' => '/^[2-467]\d{3}$/',
'fixed' => '/^(?:[267]\d|3[0-5]|4[4-69])\d{2}$/',
'emergency' => '/^911$/',
],
'possible' => [
'general' => '/^\d{4}$/',
'fixed' => '/^\d{4}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,29 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '376',
'patterns' => [
'national' => [
'general' => '/^(?:[346-9]|180)\d{5}$/',
'fixed' => '/^[78]\d{5}$/',
'mobile' => '/^[346]\d{5}$/',
'tollfree' => '/^180[02]\d{4}$/',
'premium' => '/^9\d{5}$/',
'emergency' => '/^11[0268]$/',
],
'possible' => [
'general' => '/^\d{6,8}$/',
'fixed' => '/^\d{6}$/',
'mobile' => '/^\d{6}$/',
'tollfree' => '/^\d{8}$/',
'premium' => '/^\d{6}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '971',
'patterns' => [
'national' => [
'general' => '/^(?:[2-79]\d{7,8}|800\d{2,9})$/',
'fixed' => '/^[2-4679][2-8]\d{6}$/',
'mobile' => '/^5[0256]\d{7}$/',
'tollfree' => '/^(?:400\d{6}|800\d{2,9})$/',
'premium' => '/^900[02]\d{5}$/',
'shared' => '/^700[05]\d{5}$/',
'uan' => '/^600[25]\d{5}$/',
'emergency' => '/^(?:112|99[789])$/',
],
'possible' => [
'general' => '/^\d{5,12}$/',
'fixed' => '/^\d{7,8}$/',
'mobile' => '/^\d{9}$/',
'tollfree' => '/^\d{5,12}$/',
'premium' => '/^\d{9}$/',
'shared' => '/^\d{9}$/',
'uan' => '/^\d{9}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,24 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '93',
'patterns' => [
'national' => [
'general' => '/^[2-7]\d{8}$/',
'fixed' => '/^(?:[25][0-8]|[34][0-4]|6[0-5])[2-9]\d{6}$/',
'mobile' => '/^7[057-9]\d{7}$/',
'emergency' => '/^1(?:02|19)$/',
],
'possible' => [
'general' => '/^\d{7,9}$/',
'mobile' => '/^\d{9}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,34 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[2589]\d{9}$/',
'fixed' => '/^268(?:4(?:6[0-38]|84)|56[0-2])\d{4}$/',
'mobile' => '/^268(?:464|7(?:2[0-9]|64|7[0-689]|8[02-68]))\d{4}$/',
'pager' => '/^26840[69]\d{4}$/',
'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
'premium' => '/^900[2-9]\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
'voip' => '/^26848[01]\d{4}$/',
'emergency' => '/^9(?:11|99)$/',
],
'possible' => [
'general' => '/^\d{7}(?:\d{3})?$/',
'mobile' => '/^\d{10}$/',
'pager' => '/^\d{10}$/',
'tollfree' => '/^\d{10}$/',
'premium' => '/^\d{10}$/',
'personal' => '/^\d{10}$/',
'voip' => '/^\d{10}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[2589]\d{9}$/',
'fixed' => '/^2644(?:6[12]|9[78])\d{4}$/',
'mobile' => '/^264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}$/',
'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
'premium' => '/^900[2-9]\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
'emergency' => '/^911$/',
],
'possible' => [
'general' => '/^\d{7}(?:\d{3})?$/',
'mobile' => '/^\d{10}$/',
'tollfree' => '/^\d{10}$/',
'premium' => '/^\d{10}$/',
'personal' => '/^\d{10}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '355',
'patterns' => [
'national' => [
'general' => '/^(?:[2-57]\d{7}|6\d{8}|8\d{5,7}|9\d{5})$/',
'fixed' => '/^(?:2(?:[168][1-9]|[247]\d|9[1-7])|3(?:1[1-3]|[2-6]\d|[79][1-8]|8[1-9])|4\d{2}|5(?:1[1-4]|[2-578]\d|6[1-5]|9[1-7])|8(?:[19][1-5]|[2-6]\d|[78][1-7]))\d{5}$/',
'mobile' => '/^6[6-9]\d{7}$/',
'tollfree' => '/^800\d{4}$/',
'premium' => '/^900\d{3}$/',
'shared' => '/^808\d{3}$/',
'personal' => '/^700\d{5}$/',
'emergency' => '/^12[789]$/',
],
'possible' => [
'general' => '/^\d{5,9}$/',
'fixed' => '/^\d{5,8}$/',
'mobile' => '/^\d{9}$/',
'tollfree' => '/^\d{7}$/',
'premium' => '/^\d{6}$/',
'shared' => '/^\d{6}$/',
'personal' => '/^\d{8}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,34 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '374',
'patterns' => [
'national' => [
'general' => '/^[1-9]\d{7}$/',
'fixed' => '/^(?:10\d|2(?:2[2-46]|3[1-8]|4[2-69]|5[2-7]|6[1-9]|8[1-7])|3[12]2|47\d)\d{5}$/',
'mobile' => '/^(?:55|77|9[1-9])\d{6}$/',
'tollfree' => '/^800\d{5}$/',
'premium' => '/^90[016]\d{5}$/',
'shared' => '/^80[1-4]\d{5}$/',
'voip' => '/^60[2-6]\d{5}$/',
'shortcode' => '/^(?:8[1-7]\d{2}|1(?:0[04-9]|[1-9]\d))$/',
'emergency' => '/^10[123]$/',
],
'possible' => [
'general' => '/^\d{5,8}$/',
'mobile' => '/^\d{8}$/',
'tollfree' => '/^\d{8}$/',
'premium' => '/^\d{8}$/',
'shared' => '/^\d{8}$/',
'voip' => '/^\d{8}$/',
'shortcode' => '/^\d{3,4}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '244',
'patterns' => [
'national' => [
'general' => '/^[29]\d{8}$/',
'fixed' => '/^2\d(?:[26-9]\d|\d[26-9])\d{5}$/',
'mobile' => '/^9[1-4]\d{7}$/',
'emergency' => '/^11[235]$/',
],
'possible' => [
'general' => '/^\d{9}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '54',
'patterns' => [
'national' => [
'general' => '/^(?:[1-368]\d{9}|9\d{10})$/',
'fixed' => '/^(?:11\d{8}|(?:2(?:2(?:[013]\d|2[13-79]|4[1-6]|5[2457]|6[124-8]|7[1-4]|8[13-6]|9[1267])|3(?:1[467]|2[03-6]|3[13-8]|[49][2-6]|5[2-8]|[067]\d)|4(?:7[3-8]|9\d)|6(?:[01346]\d|2[24-6]|5[15-8])|80\d|9(?:[0124789]\d|3[1-6]|5[234]|6[2-46]))|3(?:3(?:2[79]|6\d|8[2578])|4(?:[78]\d|0[0124-9]|[1-35]\d|4[24-7]|6[02-9]|9[123678])|5(?:[138]\d|2[1245]|4[1-9]|6[2-4]|7[1-6])|6[24]\d|7(?:[0469]\d|1[1568]|2[013-9]|3[145]|5[14-8]|7[2-57]|8[0-24-9])|8(?:[013578]\d|2[15-7]|4[13-6]|6[1-357-9]|9[124]))|670\d)\d{6})$/',
'mobile' => '/^(?:675\d{7}|9(?:11[2-9]\d{7}|(?:2(?:2[013]|3[067]|49|6[01346]|80|9[147-9])|3(?:36|4[12358]|5[138]|6[24]|7[069]|8[013578]))[2-9]\d{6}|\d{4}[2-9]\d{5}))$/',
'tollfree' => '/^800\d{7}$/',
'premium' => '/^60[04579]\d{7}$/',
'uan' => '/^810\d{7}$/',
'shortcode' => '/^1(?:0[2356]|1[02-5]|21)$/',
'emergency' => '/^1(?:0[017]|28)$/',
],
'possible' => [
'general' => '/^\d{6,11}$/',
'fixed' => '/^\d{6,10}$/',
'mobile' => '/^\d{6,11}$/',
'tollfree' => '/^\d{10}$/',
'premium' => '/^\d{10}$/',
'uan' => '/^\d{10}$/',
'shortcode' => '/^\d{3}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[5689]\d{9}$/',
'fixed' => '/^6846(?:22|33|44|55|77|88|9[19])\d{4}$/',
'mobile' => '/^684(?:733|258)\d{4}$/',
'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
'premium' => '/^900[2-9]\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
'emergency' => '/^911$/',
],
'possible' => [
'general' => '/^\d{7}(?:\d{3})?$/',
'mobile' => '/^\d{10}$/',
'tollfree' => '/^\d{10}$/',
'premium' => '/^\d{10}$/',
'personal' => '/^\d{10}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,34 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '43',
'patterns' => [
'national' => [
'general' => '/^[1-9]\d{3,12}$/',
'fixed' => '/^(?:1\d{3,12}|(?:2(?:1[467]|2[13-8]|5[2357]|6[1-46-8]|7[1-8]|8[124-7]|9[1458])|3(?:1[1-8]|3[23568]|4[5-7]|5[1378]|6[1-38]|8[3-68])|4(?:2[1-8]|35|63|7[1368]|8[2457])|5(?:12|2[1-8]|3[357]|4[147]|5[12578]|6[37])|6(?:13|2[1-47]|4[1-35-8]|5[468]|62)|7(?:2[1-8]|3[25]|4[13478]|5[68]|6[16-8]|7[1-6]|9[45]))\d{3,10})$/',
'mobile' => '/^6(?:44|5[0-3579]|6[013-9]|[7-9]\d)\d{4,10}$/',
'tollfree' => '/^80[02]\d{6,10}$/',
'premium' => '/^(?:711|9(?:0[01]|3[019]))\d{6,10}$/',
'shared' => '/^8(?:10|2[018])\d{6,10}$/',
'voip' => '/^780\d{6,10}$/',
'uan' => '/^(?:5(?:(?:0[1-9]|17)\d{2,10}|[79]\d{3,11})|720\d{6,10})$/',
'emergency' => '/^1(?:[12]2|33|44)$/',
],
'possible' => [
'general' => '/^\d{3,13}$/',
'mobile' => '/^\d{7,13}$/',
'tollfree' => '/^\d{9,13}$/',
'premium' => '/^\d{9,13}$/',
'shared' => '/^\d{9,13}$/',
'voip' => '/^\d{9,13}$/',
'uan' => '/^\d{5,13}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,37 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '61',
'patterns' => [
'national' => [
'general' => '/^[1-578]\d{5,9}$/',
'fixed' => '/^(?:[237]\d{8}|8(?:[68]\d{3}|7[0-69]\d{2}|9(?:[02-9]\d{2}|1(?:[0-57-9]\d|6[0135-9])))\d{4})$/',
'mobile' => '/^(?:14(?:5\d|71)\d{5}|4(?:[0-2]\d|3[0-57-9]|4[47-9]|5[0-35-9]|6[6-9]|[79][07-9]|8[17-9])\d{6})$/',
'pager' => '/^16\d{3,7}$/',
'tollfree' => '/^180(?:0\d{3}|2)\d{3}$/',
'premium' => '/^19(?:0[0126]\d{6}|[13-5]\d{3}|[679]\d{5})$/',
'shared' => '/^13(?:00\d{2})?\d{4}$/',
'personal' => '/^500\d{6}$/',
'voip' => '/^550\d{6}$/',
'emergency' => '/^(?:000|112)$/',
],
'possible' => [
'general' => '/^\d{6,10}$/',
'fixed' => '/^\d{8,9}$/',
'mobile' => '/^\d{9}$/',
'pager' => '/^\d{5,9}$/',
'tollfree' => '/^\d{7,10}$/',
'premium' => '/^\d{6,10}$/',
'shared' => '/^\d{6,10}$/',
'personal' => '/^\d{9}$/',
'voip' => '/^\d{9}$/',
'emergency' => '/^\d{3}$/',
],
],
];

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '297',
'patterns' => [
'national' => [
'general' => '/^[25-9]\\d{6}$/',
'fixed' => '/^5(?:2\\d|8[1-9])\\d{4}$/',
'mobile' => '/^(?:5(?:6\\d|9[2-478])|6(?:[039]0|22|4[01]|6[0-2])|7[34]\\d|9(?:6[45]|9[4-8]))\\d{4}$/',
'tollfree' => '/^800\\d{4}$/',
'premium' => '/^900\\d{4}$/',
'voip' => '/^(?:28\\d{5}|501\\d{4})$/',
'emergency' => '/^(?:100|911)$/',
],
'possible' => [
'general' => '/^\\d{7}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,31 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '358',
'patterns' => [
'national' => [
'general' => '/^(?:[135]\\d{5,9}|[27]\\d{4,9}|4\\d{5,10}|6\\d{7,8}|8\\d{6,9})$/',
'fixed' => '/^18[1-8]\\d{3,9}$/',
'mobile' => '/^(?:4\\d{5,10}|50\\d{4,8})$/',
'tollfree' => '/^800\\d{4,7}$/',
'premium' => '/^[67]00\\d{5,6}$/',
'uan' => '/^(?:[13]0\\d{4,8}|2(?:0(?:[016-8]\\d{3,7}|[2-59]\\d{2,7})|9\\d{4,8})|60(?:[12]\\d{5,6}|6\\d{7})|7(?:1\\d{7}|3\\d{8}|5[03-9]\\d{2,7}))$/',
'emergency' => '/^112$/',
],
'possible' => [
'general' => '/^\\d{5,12}$/',
'fixed' => '/^\\d{6,12}$/',
'mobile' => '/^\\d{6,11}$/',
'tollfree' => '/^\\d{7,10}$/',
'premium' => '/^\\d{8,9}$/',
'uan' => '/^\\d{5,10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,28 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '994',
'patterns' => [
'national' => [
'general' => '/^[1-9]\\d{8}$/',
'fixed' => '/^(?:1[28]\\d|2(?:02|1[24]|2[2-4]|33|[45]2|6[23])|365)\\d{6}$/',
'mobile' => '/^(?:4[04]|5[015]|60|7[07])\\d{7}$/',
'tollfree' => '/^88\\d{7}$/',
'premium' => '/^900200\\d{3}$/',
'emergency' => '/^1(?:0[123]|12)$/',
],
'possible' => [
'general' => '/^\\d{7,9}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{9}$/',
'premium' => '/^\\d{9}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '387',
'patterns' => [
'national' => [
'general' => '/^[3-9]\\d{7,8}$/',
'fixed' => '/^(?:[35]\\d|49)\\d{6}$/',
'mobile' => '/^6(?:03|44|71|[1-356])\\d{6}$/',
'tollfree' => '/^8[08]\\d{6}$/',
'premium' => '/^9[0246]\\d{6}$/',
'shared' => '/^8[12]\\d{6}$/',
'uan' => '/^70[23]\\d{5}$/',
'emergency' => '/^12[234]$/',
],
'possible' => [
'general' => '/^\\d{6,9}$/',
'fixed' => '/^\\d{6,8}$/',
'mobile' => '/^\\d{8,9}$/',
'tollfree' => '/^\\d{8}$/',
'premium' => '/^\\d{8}$/',
'shared' => '/^\\d{8}$/',
'uan' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[2589]\\d{9}$/',
'fixed' => '/^246[2-9]\\d{6}$/',
'mobile' => '/^246(?:(?:2[346]|45|82)\\d|25[0-4])\\d{4}$/',
'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
'premium' => '/^900[2-9]\\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
'emergency' => '/^[235]11$/',
],
'possible' => [
'general' => '/^\\d{7}(?:\\d{3})?$/',
'mobile' => '/^\\d{10}$/',
'tollfree' => '/^\\d{10}$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,31 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '880',
'patterns' => [
'national' => [
'general' => '/^(?:[2-79]\\d{5,9}|1\\d{9}|8[0-7]\\d{4,8})$/',
'fixed' => '/^(?:2(?:7(?:1[0-267]|2[0-289]|3[0-29]|[46][01]|5[1-3]|7[017]|91)|8(?:0[125]|[139][1-6]|2[0157-9]|6[1-35]|7[1-5]|8[1-8])|9(?:0[0-2]|1[1-4]|2[568]|3[3-6]|5[5-7]|6[0167]|7[15]|8[016-8]))\\d{4}|3(?:12?[5-7]\\d{2}|0(?:2(?:[025-79]\\d|[348]\\d{1,2})|3(?:[2-4]\\d|[56]\\d?))|2(?:1\\d{2}|2(?:[12]\\d|[35]\\d{1,2}|4\\d?))|3(?:1\\d{2}|2(?:[2356]\\d|4\\d{1,2}))|4(?:1\\d{2}|2(?:2\\d{1,2}|[47]|5\\d{2}))|5(?:1\\d{2}|29)|[67]1\\d{2}|8(?:1\\d{2}|2(?:2\\d{2}|3|4\\d))|)\\d{3}|4(?:0(?:2(?:[09]\\d|7)|33\\d{2})|1\\d{3}|2(?:1\\d{2}|2(?:[25]\\d?|[348]\\d|[67]\\d{1,2}))|3(?:1\\d{2}(?:\\d{2})?|2(?:[045]\\d|[236-9]\\d{1,2})|32\\d{2})|4(?:[18]\\d{2}|2(?:[2-46]\\d{2}|3)|5[25]\\d{2})|5(?:1\\d{2}|2(?:3\\d|5))|6(?:[18]\\d{2}|2(?:3(?:\\d{2})?|[46]\\d{1,2}|5\\d{2}|7\\d)|5(?:3\\d?|4\\d|[57]\\d{1,2}|6\\d{2}|8))|71\\d{2}|8(?:[18]\\d{2}|23\\d{2}|54\\d{2})|9(?:[18]\\d{2}|2[2-5]\\d{2}|53\\d{1,2}))\\d{3}|5(?:02[03489]\\d{2}|1\\d{2}|2(?:1\\d{2}|2(?:2(?:\\d{2})?|[457]\\d{2}))|3(?:1\\d{2}|2(?:[37](?:\\d{2})?|[569]\\d{2}))|4(?:1\\d{2}|2[46]\\d{2})|5(?:1\\d{2}|26\\d{1,2})|6(?:[18]\\d{2}|2|53\\d{2})|7(?:1|24)\\d{2}|8(?:1|26)\\d{2}|91\\d{2})\\d{3}|6(?:0(?:1\\d{2}|2(?:3\\d{2}|4\\d{1,2}))|2(?:2[2-5]\\d{2}|5(?:[3-5]\\d{2}|7)|8\\d{2})|3(?:1|2[3478])\\d{2}|4(?:1|2[34])\\d{2}|5(?:1|2[47])\\d{2}|6(?:[18]\\d{2}|6(?:2(?:2\\d|[34]\\d{2})|5(?:[24]\\d{2}|3\\d|5\\d{1,2})))|72[2-5]\\d{2}|8(?:1\\d{2}|2[2-5]\\d{2})|9(?:1\\d{2}|2[2-6]\\d{2}))\\d{3}|7(?:(?:02|[3-589]1|6[12]|72[24])\\d{2}|21\\d{3}|32)\\d{3}|8(?:(?:4[12]|[5-7]2|1\\d?)|(?:0|3[12]|[5-7]1|217)\\d)\\d{4}|9(?:[35]1|(?:[024]2|81)\\d|(?:1|[24]1)\\d{2})\\d{3})$/',
'mobile' => '/^(?:1[13-9]\\d|(?:3[78]|44)[02-9]|6(?:44|6[02-9]))\\d{7}$/',
'tollfree' => '/^80[03]\\d{7}$/',
'voip' => '/^96(?:0[49]|1[0-4]|6[69])\\d{6}$/',
'shortcode' => '/^1(?:0(?:[39]|5(?:0\\d|[1-4])|6\\d{2}|7[0-4]|8[0-29])|1[6-9]|2(?:2[0-5]|[34])|3(?:1\\d?|3\\d|6[3-6])|4(?:0\\d|1\\d{2})|5[2-9])$/',
'emergency' => '/^(?:10[0-2]|999)$/',
],
'possible' => [
'general' => '/^\\d{6,10}$/',
'fixed' => '/^\\d{6,9}$/',
'mobile' => '/^\\d{10}$/',
'tollfree' => '/^\\d{10}$/',
'voip' => '/^\\d{10}$/',
'shortcode' => '/^\\d{3,5}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,31 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '32',
'patterns' => [
'national' => [
'general' => '/^[1-9]\\d{7,8}$/',
'fixed' => '/^(?:(?:1[0-69]|[23][2-8]|[49][23]|5\\d|6[013-57-9]|71)\\d{6}|8(?:0[1-9]|[1-79]\\d)\\d{5})$/',
'mobile' => '/^4(?:[679]\\d|8[03-9])\\d{6}$/',
'tollfree' => '/^800\\d{5}$/',
'premium' => '/^(?:90|7[07])\\d{6}$/',
'uan' => '/^78\\d{6}$/',
'emergency' => '/^1(?:0[01]|12)$/',
],
'possible' => [
'general' => '/^\\d{8,9}$/',
'fixed' => '/^\\d{8}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{8}$/',
'premium' => '/^\\d{8}$/',
'uan' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '226',
'patterns' => [
'national' => [
'general' => '/^[24-7]\\d{7}$/',
'fixed' => '/^(?:20(?:49|5[23]|9[016-9])|40(?:4[56]|5[4-6]|7[0179])|50[34]\\d)\\d{4}$/',
'mobile' => '/^(?:6(?:[056]\\d|1[0-3]|8[0-2]|90)|7(?:[02-68]\\d|1[0-4689]|7[0-69]|9[0-689]))\\d{5}$/',
'emergency' => '/^1[78]$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{2}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '359',
'patterns' => [
'national' => [
'general' => '/^(?:[23567]\\d{5,7}|[489]\\d{6,8})$/',
'fixed' => '/^(?:2(?:[0-8]\\d{5,6}|9\\d{4,6})|(?:[36]\\d|5[1-9]|8[1-6]|9[1-7])\\d{5,6}|(?:4(?:[124-7]\\d|3[1-6])|7(?:0[1-9]|[1-9]\\d))\\d{4,5})$/',
'mobile' => '/^(?:(?:8[7-9]|98)\\d{7}|4(?:3[0789]|8\\d)\\d{5})$/',
'tollfree' => '/^800\\d{5}$/',
'premium' => '/^90\\d{6}$/',
'personal' => '/^700\\d{5}$/',
'emergency' => '/^1(?:12|50|6[06])$/',
],
'possible' => [
'general' => '/^\\d{5,9}$/',
'fixed' => '/^\\d{5,8}$/',
'mobile' => '/^\\d{8,9}$/',
'tollfree' => '/^\\d{8}$/',
'premium' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '973',
'patterns' => [
'national' => [
'general' => '/^[136-9]\\d{7}$/',
'fixed' => '/^(?:1(?:3[3-6]|6[0156]|7\\d)\\d|6(?:1[16]\\d|6(?:0\\d|3[12]|44)|9(?:69|9[6-9]))|77\\d{2})\\d{4}$/',
'mobile' => '/^(?:3(?:[23469]\\d|5[35]|77|8[348])\\d|6(?:1[16]\\d|6(?:[06]\\d|3[03-9]|44)|9(?:69|9[6-9]))|77\\d{2})\\d{4}$/',
'tollfree' => '/^80\\d{6}$/',
'premium' => '/^(?:87|9[014578])\\d{6}$/',
'shared' => '/^84\\d{6}$/',
'emergency' => '/^999$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '257',
'patterns' => [
'national' => [
'general' => '/^[27]\\d{7}$/',
'fixed' => '/^22(?:2[0-7]|[3-5]0)\\d{4}$/',
'mobile' => '/^(?:29\\d|7(?:1[1-3]|[4-9]\\d))\\d{5}$/',
'emergency' => '/^11[78]$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,31 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '229',
'patterns' => [
'national' => [
'general' => '/^(?:[2689]\\d{7}|7\\d{3})$/',
'fixed' => '/^2(?:02|1[037]|2[45]|3[68])\\d{5}$/',
'mobile' => '/^(?:6[46]|9[03-8])\\d{6}$/',
'tollfree' => '/^7[3-5]\\d{2}$/',
'voip' => '/^857[58]\\d{4}$/',
'uan' => '/^81\\d{6}$/',
'emergency' => '/^11[78]$/',
],
'possible' => [
'general' => '/^\\d{4,8}$/',
'fixed' => '/^\\d{8}$/',
'mobile' => '/^\\d{8}$/',
'tollfree' => '/^\\d{4}$/',
'voip' => '/^\\d{8}$/',
'uan' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '590',
'patterns' => [
'national' => [
'general' => '/^[56]\\d{8}$/',
'fixed' => '/^590(?:2[7-9]|5[12]|87)\\d{4}$/',
'mobile' => '/^690(?:10|2[27]|66|77|8[78])\\d{4}$/',
'emergency' => '/^18$/',
],
'possible' => [
'general' => '/^\\d{9}$/',
'emergency' => '/^\\d{2}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[4589]\\d{9}$/',
'fixed' => '/^441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}$/',
'mobile' => '/^441(?:[37]\\d|5[0-39])\\d{5}$/',
'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
'premium' => '/^900[2-9]\\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
'emergency' => '/^911$/',
],
'possible' => [
'general' => '/^\\d{7}(?:\\d{3})?$/',
'mobile' => '/^\\d{10}$/',
'tollfree' => '/^\\d{10}$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '673',
'patterns' => [
'national' => [
'general' => '/^[2-578]\\d{6}$/',
'fixed' => '/^[2-5]\\d{6}$/',
'mobile' => '/^[78]\\d{6}$/',
'emergency' => '/^99[135]$/',
],
'possible' => [
'general' => '/^\\d{7}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '591',
'patterns' => [
'national' => [
'general' => '/^[23467]\\d{7}$/',
'fixed' => '/^(?:2(?:2\\d{2}|5(?:11|[258]\\d|9[67])|6(?:12|2\\d|9[34])|8(?:2[34]|39|62))|3(?:3\\d{2}|4(?:6\\d|8[24])|8(?:25|42|5[257]|86|9[25])|9(?:2\\d|3[234]|4[248]|5[24]|6[2-6]|7\\d))|4(?:4\\d{2}|6(?:11|[24689]\\d|72)))\\d{4}$/',
'mobile' => '/^[67]\\d{7}$/',
'emergency' => '/^11[089]$/',
],
'possible' => [
'general' => '/^\\d{7,8}$/',
'fixed' => '/^\\d{7,8}$/',
'mobile' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '599',
'patterns' => [
'national' => [
'general' => '/^[347]\\d{6}$/',
'fixed' => '/^(?:318[023]|416[0239]|7(?:1[578]|50)\\d)\\d{3}$/',
'mobile' => '/^(?:318[1456]|416[15-8]|7(?:0[01]|[89]\\d)\\d)\\d{3}$/',
'emergency' => '/^(?:112|911)$/',
],
'possible' => [
'general' => '/^\\d{7}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,28 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '55',
'patterns' => [
'national' => [
'general' => '/^(?:[1-46-9]\\d{7,10}|5\\d{8,9})$/',
'fixed' => '/^(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])[2-5]\\d{7}$/',
'mobile' => '/^(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])9[6-9]\\d{7}$/',
'tollfree' => '/^800\\d{6,7}$/',
'premium' => '/^[359]00\\d{6,7}$/',
'shared' => '/^[34]00\\d{5}$/',
'emergency' => '/^(?:1(?:12|28|9[023])|911)$/',
],
'possible' => [
'general' => '/^\\d{8,11}$/',
'mobile' => '/^\\d{11}$/',
'shared' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^[2589]\\d{9}$/',
'fixed' => '/^242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}$/',
'mobile' => '/^242(?:3(?:5[79]|[79]5)|4(?:[2-4][1-9]|5[1-8]|6[2-8]|7\\d|81)|5(?:2[45]|3[35]|44|5[1-9]|65|77)|6[34]6|727)\\d{4}$/',
'tollfree' => '/^(?:242300\\d{4}|8(?:00|55|66|77|88)[2-9]\\d{6})$/',
'premium' => '/^900[2-9]\\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
'emergency' => '/^91[19]$/',
],
'possible' => [
'general' => '/^\\d{7}(?:\\d{3})?$/',
'mobile' => '/^\\d{10}$/',
'tollfree' => '/^\\d{10}$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '975',
'patterns' => [
'national' => [
'general' => '/^[1-8]\\d{6,7}$/',
'fixed' => '/^(?:2[3-6]|[34][5-7]|5[236]|6[2-46]|7[246]|8[2-4])\\d{5}$/',
'mobile' => '/^[17]7\\d{6}$/',
'emergency' => '/^11[023]$/',
],
'possible' => [
'general' => '/^\\d{6,8}$/',
'fixed' => '/^\\d{6,7}$/',
'mobile' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,29 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '267',
'patterns' => [
'national' => [
'general' => '/^[2-79]\\d{6,7}$/',
'fixed' => '/^(?:2(?:4[0-48]|6[0-24]|9[0578])|3(?:1[0235-9]|55|6\\d|7[01]|9[0-57])|4(?:6[03]|7[1267]|9[0-5])|5(?:3[0389]|4[0489]|7[1-47]|88|9[0-49])|6(?:2[1-35]|5[149]|8[067]))\\d{4}$/',
'mobile' => '/^7(?:[1-35]\\d{6}|[46][0-7]\\d{5}|7[01]\\d{5})$/',
'premium' => '/^90\\d{5}$/',
'voip' => '/^79[12][01]\\d{4}$/',
'emergency' => '/^99[789]$/',
],
'possible' => [
'general' => '/^\\d{7,8}$/',
'fixed' => '/^\\d{7}$/',
'mobile' => '/^\\d{8}$/',
'premium' => '/^\\d{7}$/',
'voip' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,29 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '375',
'patterns' => [
'national' => [
'general' => '/^(?:[1-4]\\d{8}|[89]\\d{9,10})$/',
'fixed' => '/^(?:1(?:5(?:1[1-5]|2\\d|6[2-4]|9[1-7])|6(?:[235]\\d|4[1-7])|7\\d{2})|2(?:1(?:[246]\\d|3[0-35-9]|5[1-9])|2(?:[235]\\d|4[0-8])|3(?:2\\d|3[02-79]|4[024-7]|5[0-7])))\\d{5}$/',
'mobile' => '/^(?:2(?:5[5679]|9[1-9])|33\\d|44\\d)\\d{6}$/',
'tollfree' => '/^8(?:0[13]|20\\d)\\d{7}$/',
'premium' => '/^(?:810|902)\\d{7}$/',
'emergency' => '/^1(?:0[123]|12)$/',
],
'possible' => [
'general' => '/^\\d{7,11}$/',
'fixed' => '/^\\d{7,9}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{10,11}$/',
'premium' => '/^\\d{10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,27 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '501',
'patterns' => [
'national' => [
'general' => '/^(?:[2-8]\\d{6}|0\\d{10})$/',
'fixed' => '/^[234578][02]\\d{5}$/',
'mobile' => '/^6[0-367]\\d{5}$/',
'tollfree' => '/^0800\\d{7}$/',
'emergency' => '/^9(?:0|11)$/',
],
'possible' => [
'general' => '/^\\d{7}(?:\\d{4})?$/',
'fixed' => '/^\\d{7}$/',
'mobile' => '/^\\d{7}$/',
'tollfree' => '/^\\d{11}$/',
'emergency' => '/^\\d{2,3}$/',
],
],
];

View File

@ -0,0 +1,28 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '1',
'patterns' => [
'national' => [
'general' => '/^(?:[2-9]\\d{9}|3\\d{6})$/',
'fixed' => '/^(?:(?:2(?:04|[23]6|[48]9|50)|3(?:06|43|65)|4(?:03|1[68]|3[178]|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|39|47)|7(?:0[059]|80|78)|8(?:[06]7|19|73)|90[25])[2-9]\\d{6}|310\\d{4})$/',
'mobile' => '/^(?:2(?:04|[23]6|[48]9|50)|3(?:06|43|65)|4(?:03|1[68]|3[178]|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|39|47)|7(?:0[059]|80|78)|8(?:[06]7|19|73)|90[25])[2-9]\\d{6}$/',
'tollfree' => '/^(?:8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4})$/',
'premium' => '/^900[2-9]\\d{6}$/',
'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
'emergency' => '/^(?:112|911)$/',
],
'possible' => [
'general' => '/^\\d{7}(?:\\d{3})?$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{10}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '61',
'patterns' => [
'national' => [
'general' => '/^[1458]\\d{5,9}$/',
'fixed' => '/^89162\\d{4}$/',
'mobile' => '/^4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}$/',
'tollfree' => '/^1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}$/',
'premium' => '/^190[0126]\\d{6}$/',
'personal' => '/^500\\d{6}$/',
'voip' => '/^550\\d{6}$/',
'emergency' => '/^(?:000|112)$/',
],
'possible' => [
'general' => '/^\\d{6,10}$/',
'fixed' => '/^\\d{8,9}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{6,10}$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{9}$/',
'voip' => '/^\\d{9}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '243',
'patterns' => [
'national' => [
'general' => '/^(?:[1-6]\\d{6}|8\\d{6,8}|9\\d{8})$/',
'fixed' => '/^[1-6]\\d{6}$/',
'mobile' => '/^(?:8(?:[0-259]\\d{2}|[48])\\d{5}|9[7-9]\\d{7})$/',
],
'possible' => [
'general' => '/^\\d{7,9}$/',
'fixed' => '/^\\d{7}$/',
],
],
];

View File

@ -0,0 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '236',
'patterns' => [
'national' => [
'general' => '/^[278]\\d{7}$/',
'fixed' => '/^2[12]\\d{6}$/',
'mobile' => '/^7[0257]\\d{6}$/',
'premium' => '/^8776\\d{4}$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
],
],
];

View File

@ -0,0 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '242',
'patterns' => [
'national' => [
'general' => '/^[028]\\d{8}$/',
'fixed' => '/^222[1-589]\\d{5}$/',
'mobile' => '/^0[14-6]\\d{7}$/',
'tollfree' => '/^800\\d{6}$/',
],
'possible' => [
'general' => '/^\\d{9}$/',
],
],
];

View File

@ -0,0 +1,35 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '41',
'patterns' => [
'national' => [
'general' => '/^(?:[2-9]\\d{8}|860\\d{9})$/',
'fixed' => '/^(?:2[12467]|3[1-4]|4[134]|5[12568]|6[12]|[7-9]1)\\d{7}$/',
'mobile' => '/^7[46-9]\\d{7}$/',
'tollfree' => '/^800\\d{6}$/',
'premium' => '/^90[016]\\d{6}$/',
'shared' => '/^84[0248]\\d{6}$/',
'personal' => '/^878\\d{6}$/',
'voicemail' => '/^860\\d{9}$/',
'emergency' => '/^1(?:1[278]|44)$/',
],
'possible' => [
'general' => '/^\\d{9}(?:\\d{3})?$/',
'fixed' => '/^\\d{9}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{9}$/',
'premium' => '/^\\d{9}$/',
'shared' => '/^\\d{9}$/',
'personal' => '/^\\d{9}$/',
'voicemail' => '/^\\d{12}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '225',
'patterns' => [
'national' => [
'general' => '/^[02-6]\\d{7}$/',
'fixed' => '/^(?:2(?:0[023]|1[02357]|[23][045]|4[03-5])|3(?:0[06]|1[069]|[2-4][07]|5[09]|6[08]))\\d{5}$/',
'mobile' => '/^(?:0[1-9]|4[0-24-9]|5[057-9]|6[05679])\\d{6}$/',
'emergency' => '/^1(?:1[01]|[78]0)$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '682',
'patterns' => [
'national' => [
'general' => '/^[2-57]\\d{4}$/',
'fixed' => '/^(?:2\\d|3[13-7]|4[1-5])\\d{3}$/',
'mobile' => '/^(?:5[0-68]|7\\d)\\d{3}$/',
'emergency' => '/^99[689]$/',
],
'possible' => [
'general' => '/^\\d{5}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,31 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '56',
'patterns' => [
'national' => [
'general' => '/^(?:[2-9]|600|123)\\d{7,8}$/',
'fixed' => '/^(?:(?:[23]2|41|58)\\d{7}|(?:3[3-5]|4[235]|5[1-357]|6[13-57]|7[1-35])\\d{6,7})$/',
'mobile' => '/^9[5-9]\\d{7}$/',
'tollfree' => '/^(?:800\\d{6}|1230\\d{7})$/',
'shared' => '/^600\\d{7,8}$/',
'voip' => '/^44\\d{7}$/',
'emergency' => '/^13[123]$/',
],
'possible' => [
'general' => '/^\\d{6,11}$/',
'fixed' => '/^\\d{6,9}$/',
'mobile' => '/^\\d{8,9}$/',
'tollfree' => '/^\\d{9,11}$/',
'shared' => '/^\\d{10,11}$/',
'voip' => '/^\\d{9}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '237',
'patterns' => [
'national' => [
'general' => '/^[237-9]\\d{7}$/',
'fixed' => '/^(?:22|33)\\d{6}$/',
'mobile' => '/^[79]\\d{7}$/',
'tollfree' => '/^800\\d{5}$/',
'premium' => '/^88\\d{6}$/',
'emergency' => '/^1?1[37]$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{2,3}$/',
],
],
];

View File

@ -0,0 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '86',
'patterns' => [
'national' => [
'general' => '/^(?:[1-7]\\d{7,11}|8[0-357-9]\\d{6,9}|9(?:5\\d{3}|\\d{9}))$/',
'fixed' => '/^(?:21\\d{8,10}|(?:10|2[02-57-9]|3(?:11|7[179])|4(?:[15]1|3[12])|5(?:1\\d|2[37]|3[12]|51|7[13-79]|9[15])|7(?:31|5[457]|6[09]|91)|898)\\d{8}|(?:3(?:1[02-9]|35|49|5\\d|7[02-68]|9[1-68])|4(?:1[02-9]|2[179]|3[3-9]|5[2-9]|6[4789]|7\\d|8[23])|5(?:3[03-9]|4[36]|5[02-9]|6[1-46]|7[028]|80|9[2-46-9])|6(?:3[1-5]|6[0238]|9[12])|7(?:01|[17]\\d|2[248]|3[04-9]|4[3-6]|5[0-3689]|6[2368]|9[02-9])|8(?:1[236-8]|2[5-7]|[37]\\d|5[1-9]|8[3678]|9[1-7])|9(?:0[1-3689]|1[1-79]|[379]\\d|4[13]|5[1-5]))\\d{7}|80(?:29|6[03578]|7[018]|81)\\d{4})$/',
'mobile' => '/^1(?:3\\d|4[5-9]|[58][0-35-9]|66|7[3567]|18[015-9]|9[89])\\d{8}$/',
'tollfree' => '/^(?:10)?800\\d{7}$/',
'premium' => '/^16[08]\\d{5}$/',
'shared' => '/^(?:400\\d{7}|95\\d{3})$/',
'emergency' => '/^1(?:1[09]|20)$/',
],
'possible' => [
'general' => '/^\\d{4,12}$/',
'mobile' => '/^1\\d{10}$/',
'tollfree' => '/^\\d{10,12}$/',
'premium' => '/^\\d{8}$/',
'shared' => '/^\\d{5}(?:\\d{5})?$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,29 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '57',
'patterns' => [
'national' => [
'general' => '/^(?:[13]\\d{0,3}|[24-8])\\d{7}$/',
'fixed' => '/^[124-8][2-9]\\d{6}$/',
'mobile' => '/^3(?:0[0-24]|1\\d|2[01])\\d{7}$/',
'tollfree' => '/^1800\\d{7}$/',
'premium' => '/^19(?:0[01]|4[78])\\d{7}$/',
'emergency' => '/^1(?:1[29]|23|32|56)$/',
],
'possible' => [
'general' => '/^\\d{7,11}$/',
'fixed' => '/^\\d{8}$/',
'mobile' => '/^\\d{10}$/',
'tollfree' => '/^\\d{11}$/',
'premium' => '/^\\d{11}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '506',
'patterns' => [
'national' => [
'general' => '/^[24-9]\\d{7,9}$/',
'fixed' => '/^2[24-7]\\d{6}$/',
'mobile' => '/^(?:5(?:0[0-4]|7[01])\\d{5}|[67][0-2]\\d{6}|8[3-9]\\d{6})$/',
'tollfree' => '/^800\\d{7}$/',
'premium' => '/^90[059]\\d{7}$/',
'voip' => '/^(?:210[0-6]\\d{4}|4(?:0(?:[04]0\\d{4}|10[0-3]\\d{3}|2(?:00\\d|900)\\d{2}|3[01]\\d{4}|5\\d{5}|70[01]\\d{3})|1[01]\\d{5}|400\\d{4})|5100\\d{4})$/',
'shortcode' => '/^1(?:0(?:00|15|2[2-4679])|1(?:1[0-35-9]|37|[46]6|75|8[79]|9[0-379])|2(?:00|[12]2|34|55)|333|400|5(?:15|5[15])|693|7(?:00|1[789]|2[02]|[67]7))$/',
'emergency' => '/^(?:112|911)$/',
],
'possible' => [
'general' => '/^\\d{8,10}$/',
'fixed' => '/^\\d{8}$/',
'mobile' => '/^\\d{8}$/',
'tollfree' => '/^\\d{10}$/',
'premium' => '/^\\d{10}$/',
'voip' => '/^\\d{8}$/',
'shortcode' => '/^\\d{4}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '53',
'patterns' => [
'national' => [
'general' => '/^[2-57]\\d{5,7}$/',
'fixed' => '/^(?:2[1-4]\\d{5,6}|3(?:1\\d{6}|[23]\\d{4,6})|4(?:[125]\\d{5,6}|[36]\\d{6}|[78]\\d{4,6})|7\\d{6,7})$/',
'mobile' => '/^5\\d{7}$/',
'shortcode' => '/^1(?:1(?:6111|8)|40)$/',
'emergency' => '/^10[456]$/',
],
'possible' => [
'general' => '/^\\d{4,8}$/',
'mobile' => '/^\\d{8}$/',
'shortcode' => '/^\\d{3,6}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '238',
'patterns' => [
'national' => [
'general' => '/^[259]\\d{6}$/',
'fixed' => '/^2(?:2[1-7]|3[0-8]|4[12]|5[1256]|6\\d|7[1-3]|8[1-5])\\d{4}$/',
'mobile' => '/^(?:9\\d|59)\\d{5}$/',
'emergency' => '/^13[012]$/',
],
'possible' => [
'general' => '/^\\d{7}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '599',
'patterns' => [
'national' => [
'general' => '/^[169]\\d{6,7}$/',
'fixed' => '/^9(?:[48]\\d{2}|50\\d|7(?:2[0-2]|[34]\\d|6[35-7]|77))\\d{4}$/',
'mobile' => '/^9(?:5(?:[1246]\\d|3[01])|6(?:[1679]\\d|3[01]))\\d{4}$/',
'pager' => '/^955\\d{5}$/',
'shared' => '/^(?:10|69)\\d{5}$/',
'emergency' => '/^(?:112|911)$/',
],
'possible' => [
'general' => '/^\\d{7,8}$/',
'shared' => '/^\\d{7}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '61',
'patterns' => [
'national' => [
'general' => '/^[1458]\\d{5,9}$/',
'fixed' => '/^89164\\d{4}$/',
'mobile' => '/^4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}$/',
'tollfree' => '/^1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}$/',
'premium' => '/^190[0126]\\d{6}$/',
'personal' => '/^500\\d{6}$/',
'voip' => '/^550\\d{6}$/',
'emergency' => '/^(?:000|112)$/',
],
'possible' => [
'general' => '/^\\d{6,10}$/',
'fixed' => '/^\\d{8,9}$/',
'mobile' => '/^\\d{9}$/',
'tollfree' => '/^\\d{6,10}$/',
'premium' => '/^\\d{10}$/',
'personal' => '/^\\d{9}$/',
'voip' => '/^\\d{9}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,28 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '357',
'patterns' => [
'national' => [
'general' => '/^[257-9]\\d{7}$/',
'fixed' => '/^2[2-6]\\d{6}$/',
'mobile' => '/^9[5-79]\\d{6}$/',
'tollfree' => '/^800\\d{5}$/',
'premium' => '/^90[09]\\d{5}$/',
'shared' => '/^80[1-9]\\d{5}$/',
'personal' => '/^700\\d{5}$/',
'uan' => '/^(?:50|77)\\d{6}$/',
'emergency' => '/^1(?:12|99)$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '420',
'patterns' => [
'national' => [
'general' => '/^(?:[2-8]\\d{8}|9\\d{8,11})$/',
'fixed' => '/^(?:2\\d{8}|(?:3[1257-9]|4[16-9]|5[13-9])\\d{7})$/',
'mobile' => '/^(?:60[1-8]|7(?:0[2-5]|[2379]\\d))\\d{6}$/',
'tollfree' => '/^800\\d{6}$/',
'premium' => '/^9(?:0[05689]|76)\\d{6}$/',
'shared' => '/^8[134]\\d{7}$/',
'personal' => '/^70[01]\\d{6}$/',
'voip' => '/^9[17]0\\d{6}$/',
'uan' => '/^9(?:5[056]|7[234])\\d{6}$/',
'voicemail' => '/^9(?:3\\d{9}|6\\d{7,10})$/',
'shortcode' => '/^1(?:1(?:6\\d{3}|8\\d)|2\\d{2,3}|3\\d{3,4}|4\\d{3}|99)$/',
'emergency' => '/^1(?:12|5[058])$/',
],
'possible' => [
'general' => '/^\\d{9,12}$/',
'voicemail' => '/^\\d{9,12}$/',
'shortcode' => '/^\\d{4,6}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,40 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '49',
'patterns' => [
'national' => [
'general' => '/^(?:[1-35-9]\\d{3,14}|4(?:[0-8]\\d{4,12}|9(?:[0-37]\\d|4(?:[1-35-8]|4\\d?)|5\\d{1,2}|6[1-8]\\d?)\\d{2,7}))$/',
'fixed' => '/^(?:[246]\\d{5,13}|3(?:[03-9]\\d{4,13}|2\\d{9})|5(?:0[2-8]|[1256]\\d|[38][0-8]|4\\d{0,2}|[79][0-7])\\d{3,11}|7(?:0[2-8]|[1-9]\\d)\\d{3,10}|8(?:0[2-9]|[1-9]\\d)\\d{3,10}|9(?:0[6-9]|[1-9]\\d)\\d{3,10})$/',
'mobile' => '/^1(?:5[0-2579]\\d{8}|6[023]\\d{7,8}|7(?:[0-57-9]\\d?|6\\d)\\d{7})$/',
'pager' => '/^16(?:4\\d{1,10}|[89]\\d{1,11})$/',
'tollfree' => '/^800\\d{7,10}$/',
'premium' => '/^900(?:[135]\\d{6}|9\\d{7})$/',
'shared' => '/^180\\d{5,11}$/',
'personal' => '/^700\\d{8}$/',
'uan' => '/^18(?:1\\d{5,11}|[2-9]\\d{8})$/',
'voicemail' => '/^17799\\d{7,8}$/',
'shortcode' => '/^115$/',
'emergency' => '/^11[02]$/',
],
'possible' => [
'general' => '/^\\d{2,15}$/',
'mobile' => '/^\\d{10,11}$/',
'pager' => '/^\\d{4,14}$/',
'tollfree' => '/^\\d{10,13}$/',
'premium' => '/^\\d{10,11}$/',
'shared' => '/^\\d{8,14}$/',
'personal' => '/^\\d{11}$/',
'uan' => '/^\\d{8,14}$/',
'voicemail' => '/^\\d{12,13}$/',
'shortcode' => '/^\\d{3}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '253',
'patterns' => [
'national' => [
'general' => '/^[27]\\d{7}$/',
'fixed' => '/^2(?:1[2-5]|7[45])\\d{5}$/',
'mobile' => '/^77[6-8]\\d{5}$/',
'emergency' => '/^1[78]$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{2}$/',
],
],
];

View File

@ -0,0 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
return [
'code' => '45',
'patterns' => [
'national' => [
'general' => '/^[2-9]\\d{7}$/',
'fixed' => '/^(?:[2-7]\\d|8[126-9]|9[126-9])\\d{6}$/',
'mobile' => '/^(?:[2-7]\\d|8[126-9]|9[126-9])\\d{6}$/',
'tollfree' => '/^80\\d{6}$/',
'premium' => '/^90\\d{6}$/',
'emergency' => '/^112$/',
],
'possible' => [
'general' => '/^\\d{8}$/',
'emergency' => '/^\\d{3}$/',
],
],
];

Some files were not shown because too many files have changed in this diff Show More