Exemplo n.º 1
0
 /**
  * 与えられた値を、指定された dictionary 型に変換して返します。
  * @link https://heycam.github.io/webidl/#idl-dictionary Web IDL (Second Edition)
  * @link https://heycam.github.io/webidl/#idl-dictionaries Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-dictionary Web IDL
  * @link http://www.w3.org/TR/WebIDL/#idl-dictionaries Web IDL
  * @param mixed $value
  * @param string $identifier
  * @param array $pseudoTypes
  * @throws \InvalidArgumentException SplType のインスタンスが与えられた場合。
  * @throws \DomainException dictionary メンバと同じキーを持つ $value の要素について、型が合致しない場合。
  * @return array
  */
 public static function toDictionary($value, $identifier, $pseudoTypes)
 {
     if ($value instanceof \SplType) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, $identifier));
     }
     $array = self::convertToArrayAccess($value);
     $dictionary = [];
     foreach ($pseudoTypes[$identifier] as $dictionaryMemberIdentifier => $dictionaryMemberInfo) {
         if (isset($array[$dictionaryMemberIdentifier])) {
             $dictionaryMember = $array[$dictionaryMemberIdentifier];
             try {
                 $dictionary[$dictionaryMemberIdentifier] = Type::to($dictionaryMemberInfo['type'], $dictionaryMember, $pseudoTypes);
             } catch (\LogicException $exception) {
                 if ($exception instanceof \InvalidArgumentException || $exception instanceof \DomainException) {
                     throw new \DomainException(sprintf('In "%s" member of %s, expected %s', $dictionaryMemberIdentifier, $identifier, $dictionaryMemberInfo['type']), 0, $exception);
                 } else {
                     throw $exception;
                 }
             }
         } elseif (array_key_exists('default', $dictionaryMemberInfo)) {
             $dictionary[$dictionaryMemberIdentifier] = $dictionaryMemberInfo['default'];
         } elseif (isset($dictionaryMemberInfo['required'])) {
             throw new \DomainException(sprintf('In "%s" member of %s, expected %s, got none', $dictionaryMemberIdentifier, $identifier, $dictionaryMemberInfo['type']));
         }
     }
     return $dictionary;
 }
Exemplo n.º 2
0
 /**
  * 与えられた値を整数型に変換して返します。
  * @link http://www.hcn.zaq.ne.jp/___/WEB/WebIDL-ja.html#es-integers Web IDL (第2版 — 日本語訳)
  * @param boolean|integer|float|string|resource|\GMP|\SplInt $value
  * @param string $type byte、octet、short、unsigned short、long、unsigned long、long long、unsigned long long
  * @param integer|float $min 浮動小数点型で正確に扱える整数の範囲よりも、整数型で扱える整数の範囲が狭ければ (整数型が32bitである環境なら) 浮動小数点数。
  * @param integer|float $max 浮動小数点型で正確に扱える整数の範囲よりも、整数型で扱える整数の範囲が狭ければ (整数型が32bitである環境なら) 浮動小数点数。
  * @param integer $bits
  * @param booelan $signed
  * @param string $extendedAttribute 拡張属性。[EnforceRange] か [Clamp] のいずれか。
  * @return integer|float 整数型の範囲を超える場合は浮動小数点数。
  * @throws \InvalidArgumentException 配列、NULL が与えられた場合。または、GMP、SplInt 以外のオブジェクトが与えられた場合。
  * @throws \DomainException $extendedAttribute が [EnforceRange]、かつ与えられたの値が $min 〜 $max に収まらなかった場合。
  */
 private static function toInteger($value, $type, $min, $max, $bits, $signed, $extendedAttribute = null)
 {
     /** @var string 要求される型。 */
     $expectedType = sprintf('%s (an integer in the range of %s to %s)', $type, is_float($min) ? number_format($min, 0, '', '') : $min, is_float($max) ? number_format($max, 0, '', '') : $max);
     if (!self::isIntegerCastable($value)) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, $expectedType));
     }
     if ($value instanceof \GMP || is_resource($value) && get_resource_type($value) === 'GMP integer') {
         // GMP数であれば、あらかじめ文字列に変換しておく
         $value = gmp_strval($value);
     }
     /** @var integer|float 与えられた値の数値表現。整数型の範囲を超える場合は浮動小数点数。整数値となる場合、小数部があれば0方向へ丸められる。 */
     $number = is_float($value) || (double) $value < self::$phpIntMin || (double) $value > PHP_INT_MAX ? (double) $value : (int) $value;
     if ($extendedAttribute === '[EnforceRange]') {
         /** @var integer|float 与えられた値の整数表現。整数型の範囲を超える場合は浮動小数点数。 */
         $integer = self::roundTowardZero($number);
         if (!is_finite($number) || $integer < $min || $integer > $max) {
             throw new \DomainException(ErrorMessageCreator::create($value, $expectedType));
         }
     } elseif (!is_nan($number) && $extendedAttribute === '[Clamp]') {
         $number = min(max($number, $min), $max);
         $integer = is_float($number) ? round($number, 0, PHP_ROUND_HALF_EVEN) : $number;
     } elseif (!is_finite($number)) {
         $integer = 0;
     } else {
         $integer = self::modulo(self::roundTowardZero($number), pow(2, $bits));
         if ($signed && $integer >= pow(2, $bits - 1)) {
             $integer -= pow(2, $bits);
         }
     }
     return is_float($integer) && $integer >= self::$phpIntMin && $integer <= PHP_INT_MAX ? (int) $integer : $integer;
 }
Exemplo n.º 3
0
 /**
  * 与えられた値を、浮動小数点型に変換して返します。
  * @link https://heycam.github.io/webidl/#idl-unrestricted-double Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-unrestricted-double Web IDL
  * @param boolean|integer|float|string|resource|\GMP|\SplFloat $value
  * @throws \InvalidArgumentException 配列、NULL が与えられた場合。または、GMP、SplFloat 以外のオブジェクトが与えられた場合。
  * @return float
  */
 public static function toUnrestrictedDouble($value)
 {
     if (self::isFloatCastable($value)) {
         return (double) ($value instanceof \GMP || is_resource($value) && get_resource_type($value) === 'GMP integer' ? gmp_strval($value) : $value);
     } else {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, 'double (a float)'));
     }
 }
Exemplo n.º 4
0
 /**
  * 与えられた値が callable かチェックして返します。
  * @link https://heycam.github.io/webidl/#idl-callback-function Web IDL (Second Edition)
  * @link https://heycam.github.io/webidl/#idl-callback-functions Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-callback-function Web IDL
  * @link http://www.w3.org/TR/WebIDL/#idl-callback-functions Web IDL
  * @param callable $value
  * @throws \InvalidArgumentException callable でない値が与えられた場合。
  * @return object
  */
 public static function toCallbackFunction($value)
 {
     if (is_callable($value)) {
         return $value;
     } else {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, 'a callback function (a callable)'));
     }
 }
Exemplo n.º 5
0
 /**
  * 与えられた値を論理型に変換して返します。
  * @link https://heycam.github.io/webidl/#idl-boolean Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-boolean Web IDL
  * @param mixed $value
  * @throws \InvalidArgumentException SplBool 以外の SplType が与えられた場合。
  * @return boolean
  */
 public static function toBoolean($value)
 {
     if (self::isBooleanCastable($value)) {
         return (bool) $value;
     } else {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, 'a boolean'));
     }
 }
Exemplo n.º 6
0
 /**
  * 与えられた値を文字列型に変換し、列挙値のいずれかに一致するかチェックして返します。
  * @param string|\SplEnum $value
  * @param string $identifier 列挙型の識別子。
  * @param string[]|string $enum 列挙値の配列、または SplEnum を継承したクラスの完全修飾名。
  * @throws \InvalidArgumentException $value が文字列化できない場合。
  *      $value が SplEnum かつ $enum が配列である場合。または、$value が SplEnum かつ $enum がクラス名で、$value が $enum のインスタンスでない場合。
  * @throws \DomainException $value が $enum で与えられた列挙値のいずれにも一致しなかった場合。
  * @return string
  */
 public static function toEnumerationValue($value, $identifier, $enum)
 {
     $expectedType = sprintf('DOMString (a UTF-8 string) and valid %s value', $identifier);
     try {
         $string = self::toDOMString($value);
     } catch (\InvalidArgumentException $exception) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, $expectedType), 0, $exception);
     }
     if ($value instanceof \SplEnum && (!is_string($enum) || !$value instanceof $enum)) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, $expectedType));
     } elseif (!in_array($string, is_string($enum) ? (new $enum())->getConstList() : $enum, true)) {
         throw new \DomainException(ErrorMessageCreator::create($value, $expectedType));
     }
     return $string;
 }
Exemplo n.º 7
0
 /**
  * 与えられた値を、要素として指定された型のみを含む配列に変換して返します。
  * @link https://heycam.github.io/webidl/#idl-sequence Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-sequence Web IDL
  * @param mixed $traversable
  * @param string $type sequence の要素型 (sequence<T\> の T)。
  * @param array $pseudoTypes callback interface 型、列挙型、callback 関数型、または dictionary 型の識別子をキーとした型情報の配列。
  * @throws \InvalidArgumentException SplType のインスタンスが与えられた場合。
  * @throws \DomainException 与えられた配列の要素が、指定された型に合致しない場合。
  * @return array
  */
 public static function toSequence($traversable, $type, $pseudoTypes = [])
 {
     $expectedType = sprintf('%s (an array including only %s)', 'sequence<' . $type . '>', $type);
     if ($traversable instanceof \SplType) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($traversable, $expectedType));
     }
     $array = [];
     foreach (self::convertToRewindable($traversable) as $value) {
         try {
             $array[] = Type::to($type, $value, $pseudoTypes);
         } catch (\LogicException $exception) {
             if ($exception instanceof \InvalidArgumentException || $exception instanceof \DomainException) {
                 throw new \DomainException(ErrorMessageCreator::create(null, $expectedType, ''), 0, $exception);
             } else {
                 throw $exception;
             }
         }
     }
     return $array;
 }
Exemplo n.º 8
0
 /**
  * 与えられた値を、指定された型、または NULL 型に変換して返します。
  * @link https://heycam.github.io/webidl/#idl-nullable-type Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-nullable-type Web IDL
  * @param mixed $value
  * @param string $type nullable 型の内部型 (T? の T)。
  * @param array $pseudoTypes callback interface 型、列挙型、callback 関数型、または dictionary 型の識別子をキーとした型情報の配列。
  * @throws \InvalidArgumentException 指定された型、または NULL 型のいずれにも合致しない値が与えられた場合。
  * @throws \DomainException 指定された型、または NULL 型のいずれにも合致しない値が与えられた場合。
  * @return array
  */
 public static function toNullable($value, $type, $pseudoTypes = [])
 {
     if (is_null($value)) {
         $nullable = null;
     } else {
         try {
             $nullable = Type::to($type, $value, $pseudoTypes);
         } catch (\LogicException $exception) {
             $errorMessage = ErrorMessageCreator::create(null, sprintf('%s (%s or null)', $type . '?', $type), '');
             if ($exception instanceof \InvalidArgumentException) {
                 throw new \InvalidArgumentException($errorMessage, 0, $exception);
             } elseif ($exception instanceof \DomainException) {
                 throw new \DomainException($errorMessage, 0, $exception);
             } else {
                 throw $exception;
             }
         }
     }
     return $nullable;
 }
Exemplo n.º 9
0
 /**
  * 与えられた値が妥当な正規表現 (PCRE) パターンかチェックして返します。
  * @link https://heycam.github.io/webidl/#idl-RegExp Web IDL (Second Edition)
  * @param string $value
  * @throws \InvalidArgumentException 論理値、整数、浮動小数点数、符号化方式が UTF-8 でない文字列、配列、
  *      __toString()メソッドなどを持たないオブジェクト、リソース、または NULL が与えられた場合。
  * @throws \DomainException 妥当でない正規表現パターンが与えられた場合
  * @return string
  */
 public static function toRegExp($value)
 {
     $expectedType = 'RegExp (a UTF-8 string and valid regular expression pattern)';
     if (!self::isRegExpCastable($value)) {
         throw new \InvalidArgumentException(ErrorMessageCreator::create($value, $expectedType));
     }
     $string = (string) $value;
     set_error_handler(function ($severity, $message) use($expectedType) {
         if (strpos($message, 'preg_replace(): ') === 0) {
             throw new \DomainException(ErrorMessageCreator::create(null, $expectedType, str_replace('preg_replace(): ', '', $message)));
         } else {
             return false;
         }
     }, E_WARNING | E_DEPRECATED);
     preg_replace($string, '', '');
     restore_error_handler();
     if (PHP_VERSION_ID < 50500 && preg_match('/e[\\n a-zA-Z]*$/u', $string) === 1) {
         throw new \DomainException(ErrorMessageCreator::create(null, $expectedType, 'The /e modifier is deprecated, use preg_replace_callback instead'));
     }
     return $string;
 }
Exemplo n.º 10
0
 /**
  * @param mixed $value
  * @param string $expectedType
  * @param string|null $message
  * @param string $errorMessage
  * @dataProvider messageProvider
  */
 public function testCreate($value, $expectedType, $message, $errorMessage)
 {
     $this->assertSame($errorMessage, ErrorMessageCreator::create($value, $expectedType, $message));
 }
Exemplo n.º 11
0
 /**
  * 与えられた値を、指定された型のいずれか一つに変換して返します。
  * @link https://heycam.github.io/webidl/#idl-union Web IDL (Second Edition)
  * @link http://www.w3.org/TR/WebIDL/#idl-union Web IDL
  * @link https://heycam.github.io/webidl/#es-union Web IDL (Second Edition)
  * @param mixed $value
  * @param string $unitTypeString 共用体型。先頭、末尾の丸括弧も含む文字列。
  * @param array $pseudoTypes callback interface 型、列挙型、callback 関数型、または dictionary 型の識別子をキーとした型情報の配列。
  * @throws \InvalidArgumentException 指定された型のいずれにも一致しない値が与えられた場合。
  * @throws \DomainException 指定された型のいずれにも一致しない値が与えられた場合。
  * @return mixed
  */
 public static function toUnion($value, $unitTypeString, $pseudoTypes = [])
 {
     $flattenedTypesAndNullableNums = self::getFlattenedTypesAndNullableNums($unitTypeString);
     if ($flattenedTypesAndNullableNums['numberOfNullableMemberTypes'] === 1 && is_null($value)) {
         return null;
     }
     foreach ($flattenedTypesAndNullableNums['flattenedMemberTypes'] as $type) {
         $genericTypes[$type] = self::getGenericType($type, $pseudoTypes);
     }
     if (is_object($value) || $value instanceof \__PHP_Incomplete_Class) {
         foreach (array_keys($genericTypes, 'interface') as $interfaceType) {
             try {
                 return Type::to($interfaceType, $value, $pseudoTypes);
             } catch (\LogicException $exception) {
                 if ($exception instanceof \InvalidArgumentException) {
                     $lastInvalidArgumentException = $exception;
                 } elseif ($exception instanceof \DomainException) {
                     $lastDomainException = $exception;
                 } else {
                     throw $exception;
                 }
             }
         }
         if (isset($genericTypes['object'])) {
             return $value;
         }
     }
     if (RegExpType::isRegExpCastable($value) && isset($genericTypes['RegExp'])) {
         try {
             return RegExpType::toRegExp($value);
         } catch (\LogicException $exception) {
             if ($exception instanceof \DomainException) {
                 $lastDomainException = $exception;
             } else {
                 throw $exception;
             }
         }
     }
     if (is_callable($value) && array_search('callback function', $genericTypes)) {
         return $value;
     }
     try {
         if ((is_array($value) || is_object($value) || $value instanceof \__PHP_Incomplete_Class || is_null($value)) && ($identifier = array_search('dictionary', $genericTypes)) !== false) {
             return DictionaryType::toDictionary($value, $identifier, $pseudoTypes);
         }
         if (is_array($value) || is_object($value) || $value instanceof \__PHP_Incomplete_Class || is_null($value)) {
             $type = array_search('array', $genericTypes) ?: array_search('sequence', $genericTypes) ?: array_search('FrozenArray', $genericTypes);
             if ($type) {
                 return Type::to($type, $value, $pseudoTypes);
             }
             foreach (array_keys($genericTypes, 'interface') as $interfaceType) {
                 if (isset($pseudoTypes[$interfaceType]) && ($pseudoTypes[$interfaceType] === 'callback interface' || $pseudoTypes[$interfaceType] === 'single operation callback interface')) {
                     return Type::to($interfaceType, $value, $pseudoTypes);
                 }
             }
         }
         if (is_bool($value) && isset($genericTypes['boolean'])) {
             return $value;
         }
         if ((is_int($value) || is_float($value)) && ($type = array_search('numeric', $genericTypes))) {
             return Type::to($type, $value);
         }
         if ($type = array_search('string', $genericTypes) ?: array_search('numeric', $genericTypes)) {
             return Type::to($type, $value, $pseudoTypes);
         }
         if (isset($genericTypes['boolean'])) {
             return BooleanType::toBoolean($value);
         }
     } catch (\LogicException $exception) {
         if ($exception instanceof \InvalidArgumentException) {
             $lastInvalidArgumentException = $exception;
         } elseif ($exception instanceof \DomainException) {
             $lastDomainException = $exception;
         } else {
             throw $exception;
         }
     }
     $errorMessage = ErrorMessageCreator::create($value, $unitTypeString);
     if (isset($lastDomainException)) {
         throw new \DomainException($errorMessage, 0, $lastDomainException);
     } elseif (isset($lastInvalidArgumentException)) {
         throw new \InvalidArgumentException($errorMessage, 0, $lastInvalidArgumentException);
     } else {
         throw new \InvalidArgumentException($errorMessage);
     }
 }