/** * @param AvroSchema $schema The rules to conform to. * @param mixed $datum The value to validate against $schema. * @return string|string[] An error or list of errors in the * provided $datum. When no errors exist the empty array is * returned. */ public static function getErrors(AvroSchema $schema, $datum) { switch ($schema->type) { case AvroSchema::NULL_TYPE: if (!is_null($datum)) { return self::wrongType('null', $datum); } return array(); case AvroSchema::BOOLEAN_TYPE: if (!is_bool($datum)) { return self::wrongType('boolean', $datum); } return array(); case AvroSchema::STRING_TYPE: case AvroSchema::BYTES_TYPE: if (!is_string($datum)) { return self::wrongType('string', $datum); } return array(); case AvroSchema::INT_TYPE: if (!is_int($datum)) { return self::wrongType('integer', $datum); } if (AvroSchema::INT_MIN_VALUE > $datum || $datum > AvroSchema::INT_MAX_VALUE) { return self::outOfRange(AvroSchema::INT_MIN_VALUE, AvroSchema::INT_MAX_VALUE, $datum); } return array(); case AvroSchema::LONG_TYPE: if (!is_int($datum)) { return self::wrongType('integer', $datum); } if (AvroSchema::LONG_MIN_VALUE > $datum || $datum > AvroSchema::LONG_MAX_VALUE) { return self::outOfRange(AvroSchema::LONG_MIN_VALUE, AvroSchema::LONG_MAX_VALUE, $datum); } return array(); case AvroSchema::FLOAT_TYPE: case AvroSchema::DOUBLE_TYPE: if (!is_float($datum) && !is_int($datum)) { return self::wrongType('float or integer', $datum); } return array(); case AvroSchema::ARRAY_SCHEMA: if (!is_array($datum)) { return self::wrongType('array', $datum); } $errors = array(); foreach ($datum as $d) { $result = $this->validate($schema->items(), $d); if ($result) { $errors[] = $result; } } if ($errors) { return $errors; } return array(); case AvroSchema::MAP_SCHEMA: if (!is_array($datum)) { return self::wrongType('array', $datum); } $errors = array(); foreach ($datum as $k => $v) { if (!is_string($k)) { $errors[] = self::wrongType('string key', $k); } $result = self::getErrors($schema->values(), $v); if ($result) { $errors[$k] = $result; } } return $errors; case AvroSchema::UNION_SCHEMA: $errors = array(); foreach ($schema->schemas() as $schema) { $result = self::getErrors($schema, $datum); if (!$result) { return array(); } $errors[] = $result; } if ($errors) { return array("Expected any one of these to be true", $errors); } return "No schemas provided to union"; case AvroSchema::ENUM_SCHEMA: if (!in_array($datum, $schema->symbols())) { $symbols = implode(', ', $schema->symbols); return "Expected one of {$symbols} but recieved {$datum}"; } return array(); case AvroSchema::FIXED_SCHEMA: if (!is_string($datum)) { return self::wrongType('string', $datum); } $len = strlen($datum); if ($len !== $schema->size()) { return "Expected string of length {$schema->size()}, " . "but recieved one of length {$len}"; } return array(); case AvroSchema::RECORD_SCHEMA: case AvroSchema::ERROR_SCHEMA: case AvroSchema::REQUEST_SCHEMA: if (!is_array($datum)) { return self::wrongType('array', $datum); } $errors = array(); foreach ($schema->fields() as $field) { $name = $field->name(); if (!array_key_exists($name, $datum)) { $errors[$name] = 'Missing expected field'; continue; } $result = self::getErrors($field->type(), $datum[$name]); if ($result) { $errors[$name] = $result; } } return $errors; default: return "Unknown avro schema type: {$schema->type}"; } }
/** * @param AvroSchema $field_schema * @param null|boolean|int|float|string|array $default_value * @return null|boolean|int|float|string|array * * @throws AvroException if $field_schema type is unknown. */ public function read_default_value($field_schema, $default_value) { switch ($field_schema->type()) { case AvroSchema::NULL_TYPE: return null; case AvroSchema::BOOLEAN_TYPE: return $default_value; case AvroSchema::INT_TYPE: case AvroSchema::LONG_TYPE: return (int) $default_value; case AvroSchema::FLOAT_TYPE: case AvroSchema::DOUBLE_TYPE: return (double) $default_value; case AvroSchema::STRING_TYPE: case AvroSchema::BYTES_TYPE: return $default_value; case AvroSchema::ARRAY_SCHEMA: $array = array(); foreach ($default_value as $json_val) { $val = $this->read_default_value($field_schema->items(), $json_val); $array[] = $val; } return $array; case AvroSchema::MAP_SCHEMA: $map = array(); foreach ($default_value as $key => $json_val) { $map[$key] = $this->read_default_value($field_schema->values(), $json_val); } return $map; case AvroSchema::UNION_SCHEMA: return $this->read_default_value($field_schema->schema_by_index(0), $default_value); case AvroSchema::ENUM_SCHEMA: case AvroSchema::FIXED_SCHEMA: return $default_value; case AvroSchema::RECORD_SCHEMA: $record = array(); foreach ($field_schema->fields() as $field) { $field_name = $field->name(); if (!($json_val = $default_value[$field_name])) { $json_val = $field->default_value(); } $record[$field_name] = $this->read_default_value($field->type(), $json_val); } return $record; default: throw new AvroException(sprintf('Unknown type: %s', $field_schema->type())); } }