/** * 与えられた値を、指定された 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; }
/** * 与えられた値を、要素として指定された型のみを含む配列に変換して返します。 * @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; }
/** * 与えられた値を、指定された型、または 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; }
/** * @param string $type * @param mixed $value * @param array[]|null $pseudoTypes * @param mixed $returnValue * @dataProvider toProvider */ public function testTo($type, $value, $pseudoTypes, $returnValue) { $this->assertSame($returnValue, Type::to($type, $value, $pseudoTypes)); }
/** * 与えられた値を、指定された型のいずれか一つに変換して返します。 * @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); } }