/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_string($value) && !\is_int($value) && !\is_float($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'string')); } return ConversionResult::value((string) $value); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_array($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'array')); } $errors = []; if ($typeParams) { $type = $typeParams[0]; $coerced = []; $idx = 0; foreach ($value as $v) { $result = $ctx->coerce($v, $type); if ($result->getErrors()) { $errors = \array_merge($errors, $result->errorsInIdx($idx)); if ($result->getValue() === null) { return ConversionResult::errors($errors); } } $coerced[] = $result->getValue(); ++$idx; } $value = $coerced; } else { $value = \array_values($value); } return ConversionResult::errors($errors, $value); }
/** * @param array $request * @param \ReflectionClass $class * @param callable $nameMangling * * @return ConversionResult */ public function convert(array $request, \ReflectionClass $class, callable $nameMangling) { $ctx = new Context($this, $this->coercer, $nameMangling); $object = $this->instance($class); $setter = $this->setter($object); $errors = []; foreach ($class->getProperties() as $prop) { $name = $nameMangling($prop->getName()); if (!isset($request[$name]) && !$this->reader->getPropertyAnnotation($prop, Optional::class)) { $errors[] = new MissingFieldError($name); continue; } elseif (!\array_key_exists($name, $request)) { continue; } $value = $request[$name]; $typeAnnotation = $this->reader->getPropertyAnnotation($prop, Type::class); if ($value !== null && $typeAnnotation instanceof Type) { try { $result = $this->coercer->coerce($value, $typeAnnotation->type, $ctx); } catch (CoercionException $e) { throw ConverterException::in($class->getName(), $prop->getName(), $e); } $value = $result->getValue(); $errors = \array_merge($errors, $result->errorsInField($name)); $setter->set($prop->getName(), $value); } elseif ($value === null) { $setter->set($prop->getName(), null); } } return ConversionResult::errors($errors, $object); }
/** * @param mixed $value * @param string $type * @param Context $ctx * * @return ConversionResult * @throws NoTypeException * @throws InvalidTypeException */ public function coerce($value, $type, Context $ctx) { if ($value === null) { return ConversionResult::value(null); } list($coerceType, $parameters) = $this->parseType($type); return $this->getCoercer($coerceType, $type)->coerce($value, $type, $parameters, $ctx); }
public function testPassthrough() { $input = ["a" => 1, "b" => 2]; $output = (object) $input; $coercer = new ObjectCoercer(); $this->ctx->expects($this->once())->method("convert")->with($input, $this->equalTo(new \ReflectionClass("stdClass")))->willReturn(ConversionResult::value($output)); $this->assertConvertedValue($output, $coercer->coerce($input, "object<stdClass>", ["stdClass"], $this->ctx)); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_array($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'object')); } $class = new \ReflectionClass($typeParams[0]); return $ctx->convert($value, $class); }
public function testTerminalError() { $coercer = new ArrayCoercer(); $this->ctx->expects($this->exactly(2))->method("coerce")->withConsecutive([1, "int"], [2, "int"])->willReturnOnConsecutiveCalls(ConversionResult::value(1), ConversionResult::error(new MissingFieldError())); $result = $coercer->coerce([1, 2, 3], "array<int>", ["int"], $this->ctx); $this->assertNull($result->getValue()); $this->assertCount(1, $result->getErrors()); $this->assertInstanceOf(MissingFieldError::class, $result->getErrors()[0]); $this->assertSame("[1]", $result->getErrors()[0]->getField()); }
public function testTypedKeyValueTerminalError() { $coercer = new MapCoercer(); $this->ctx->expects($this->exactly(2))->method("coerce")->withConsecutive([2, "int"], ["a", "string"])->willReturnOnConsecutiveCalls(ConversionResult::value(2), ConversionResult::error(new TypeError("object", "int"))); $result = $coercer->coerce(["a" => 2, "b" => 6, "c" => 9, "d" => 15], "map<string, int>", ["string", "int"], $this->ctx); $this->assertNull($result->getValue()); $this->assertCount(1, $result->getErrors()); $this->assertInstanceOf(TypeError::class, $result->getErrors()[0]); $this->assertSame("a", $result->getErrors()[0]->getField()); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!$typeParams || !\preg_match('!^[^<]+\\<(.+)\\>$!', $origType, $formatMatch)) { throw new InvalidTypeException("DateTime type expects format to be provided"); } $format = $formatMatch[1]; $date = \DateTime::createFromFormat($format, $value, $this->timezone); if (!$date) { return ConversionResult::error(new InvalidDateFormatError($value, $format)); } return ConversionResult::value($date); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_int($value) && !\is_string($value) && !\is_float($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'int')); } if (\is_string($value) || \is_float($value)) { $value = \filter_var((string) $value, FILTER_VALIDATE_INT); if ($value === false) { return ConversionResult::error(new UncoercibleValueError('string', 'int')); } } return ConversionResult::value($value); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_array($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'object')); } $errors = []; if (\count($typeParams) === 1) { // coerced values $type = $typeParams[0]; $coerced = []; foreach ($value as $k => $v) { $result = $ctx->coerce($v, $type); if ($result->getErrors()) { $errors = array_merge($errors, $result->errorsInField($k)); if ($result->getValue() === null) { return ConversionResult::errors($errors); } } $coerced[$k] = $result->getValue(); } $value = $coerced; } elseif (\count($typeParams) === 2) { // coerced keys and values list($keyT, $valueT) = $typeParams; if ($keyT !== "string" && $keyT !== "int") { throw InvalidTypeException::from("Map<{$keyT}, {$valueT}>"); } $coerced = []; foreach ($value as $key => $val) { $v = $ctx->coerce($val, $valueT); $k = $ctx->coerce($key, $keyT); if ($v->getErrors() || $k->getErrors()) { $errors = array_merge($errors, $v->errorsInField($key), $k->errorsInField($key)); if ($v->getValue() === null || $k->getValue() === null) { return ConversionResult::errors($errors); } } $coerced[$k->getValue()] = $v->getValue(); } $value = $coerced; } return ConversionResult::errors($errors, $value); }
/** * @inheritdoc */ public function coerce($value, $origType, array $typeParams, Context $ctx) { if (!\is_bool($value) && !\is_int($value) && !\is_string($value) && !\is_float($value)) { return ConversionResult::error(new TypeError(\gettype($value), 'bool')); } if (\is_string($value)) { $value = trim($value); if (\is_numeric($value)) { $value = (bool) (int) $value; } elseif (\in_array($value, $this->false, true)) { $value = false; } elseif (\in_array($value, $this->true, true)) { $value = true; } else { $value = (bool) $value; } } else { $value = (bool) $value; } return ConversionResult::value($value); }
public function assertConvertedValue($expected, ConversionResult $result) { $this->assertEmpty($result->getErrors()); $this->assertSame($expected, $result->getValue()); }