private static function validateEntry($typeName, $key, $value, $def, $pathStr)
{
$type = Utils::getVariableType($value);
$err = 'Error in "' . $typeName . '" type definition: expecting %s at "' . $pathStr . '", but got "' . $type . '"';
if ($def instanceof \stdClass) {
if ($def->flags & self::REQUIRED === 0 && $value === null) {
return;
}
if (($def->flags & self::MAYBE_THUNK) > 0) {
Utils::invariant(is_array($value) || is_callable($value), $err, 'array or callable');
} else {
Utils::invariant(is_array($value), $err, 'array');
}
if (!empty($def->isMap)) {
if ($def->flags & self::KEY_AS_NAME) {
$value += ['name' => $key];
}
self::validateMap($typeName, $value, $def->definition, $pathStr);
} else {
if (!empty($def->isArray)) {
if ($def->flags & self::REQUIRED) {
Utils::invariant(!empty($value), 'Error in "' . $typeName . '" type definition: ' . "Value at '{$pathStr}' cannot be empty array");
}
$err = 'Error in "' . $typeName . '" type definition: ' . "Each entry at '{$pathStr}' must be an array, but '%s' is '%s'";
foreach ($value as $arrKey => $arrValue) {
if (is_array($def->definition)) {
if ($def->flags & self::MAYBE_TYPE && $arrValue instanceof Type) {
$arrValue = ['type' => $arrValue];
}
if ($def->flags & self::MAYBE_NAME && is_string($arrValue)) {
$arrValue = ['name' => $arrValue];
}
Utils::invariant(is_array($arrValue), $err, $arrKey, Utils::getVariableType($arrValue));
if ($def->flags & self::KEY_AS_NAME) {
$arrValue += ['name' => $arrKey];
}
self::validateMap($typeName, $arrValue, $def->definition, "{$pathStr}:{$arrKey}");
} else {
self::validateEntry($typeName, $arrKey, $arrValue, $def->definition, "{$pathStr}:{$arrKey}");
}
}
} else {
throw new InvariantViolation('Error in "' . $typeName . '" type definition: ' . "unexpected definition: " . print_r($def, true));
}
}
} else {
Utils::invariant(is_int($def), 'Error in "' . $typeName . '" type definition: ' . "Definition for '{$pathStr}' is expected to be single integer value");
if ($def & self::REQUIRED) {
Utils::invariant($value !== null, 'Value at "%s" can not be null', $pathStr);
}
if (null === $value) {
return;
// Allow nulls for non-required fields
}
switch (true) {
case $def & self::ANY:
break;
case $def & self::BOOLEAN:
Utils::invariant(is_bool($value), $err, 'boolean');
break;
case $def & self::STRING:
Utils::invariant(is_string($value), $err, 'string');
break;
case $def & self::NUMERIC:
Utils::invariant(is_numeric($value), $err, 'numeric');
break;
case $def & self::FLOAT:
Utils::invariant(is_float($value), $err, 'float');
break;
case $def & self::INT:
Utils::invariant(is_int($value), $err, 'int');
break;
case $def & self::CALLBACK:
Utils::invariant(is_callable($value), $err, 'callable');
break;
case $def & self::SCALAR:
Utils::invariant(is_scalar($value), $err, 'scalar');
break;
case $def & self::NAME:
Utils::invariant(preg_match('~^[_a-zA-Z][_a-zA-Z0-9]*$~', $value), 'Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but "%s" does not.', $value);
break;
case $def & self::INPUT_TYPE:
Utils::invariant(is_callable($value) || $value instanceof InputType, $err, 'callable or InputType definition');
break;
case $def & self::OUTPUT_TYPE:
Utils::invariant(is_callable($value) || $value instanceof OutputType, $err, 'callable or OutputType definition');
break;
case $def & self::INTERFACE_TYPE:
Utils::invariant(is_callable($value) || $value instanceof InterfaceType, $err, 'callable or InterfaceType definition');
break;
case $def & self::OBJECT_TYPE:
Utils::invariant(is_callable($value) || $value instanceof ObjectType, $err, 'callable or ObjectType definition');
break;
default:
throw new InvariantViolation("Unexpected validation rule: " . $def);
}
}
}