public function validate($parents = [], $skip = [])
{
if (in_array($this, $skip, true)) {
return true;
}
$valid = true;
// Report orphaned annotations
foreach ($this->_unmerged as $annotation) {
if (!is_object($annotation)) {
Logger::notice('Unexpected type: "' . gettype($annotation) . '" in ' . $this->identity() . '->_unmerged, expecting a Annotation object');
break;
}
$class = get_class($annotation);
if (isset(static::$_nested[$class])) {
$property = static::$_nested[$class];
Logger::notice('Only one @' . str_replace('Swagger\\Annotations\\', 'SWG\\', get_class($annotation)) . '() allowed for ' . $this->identity() . " multiple found in:\n Using: " . $this->{$property}->_context . "\n Skipped: " . $annotation->_context);
} elseif ($annotation instanceof AbstractAnnotation) {
$message = 'Unexpected ' . $annotation->identity();
if (count($class::$_parents)) {
$shortNotations = [];
foreach ($class::$_parents as $_class) {
$shortNotations[] = '@' . str_replace('Swagger\\Annotations\\', 'SWG\\', $_class);
}
$message .= ', expected to be inside ' . implode(', ', $shortNotations);
}
Logger::notice($message . ' in ' . $annotation->_context);
}
$valid = false;
}
// Report conflicting key
foreach (static::$_nested as $nested) {
if (is_string($nested) || count($nested) === 1) {
continue;
}
$property = $nested[0];
if ($this->{$property} === null) {
continue;
}
$keys = [];
$keyField = $nested[1];
foreach ($this->{$property} as $item) {
if (empty($item->{$keyField})) {
Logger::notice($item->identity() . ' is missing key-field: "' . $keyField . '" in ' . $item->_context);
} elseif (isset($keys[$item->{$keyField}])) {
Logger::notice('Multiple ' . $item->_identity([]) . ' with the same ' . $keyField . '="' . $item->{$keyField} . "\":\n " . $item->_context . "\n " . $keys[$item->{$keyField}]->_context);
} else {
$keys[$item->{$keyField}] = $item;
}
}
}
if (empty($this->ref)) {
// Report missing required fields (when not a $ref)
foreach (static::$_required as $property) {
if ($this->{$property} === null || $this->{$property} === UNDEFINED) {
$message = 'Missing required field "' . $property . '" for ' . $this->identity() . ' in ' . $this->_context;
foreach (static::$_nested as $class => $nested) {
$nestedProperty = is_array($nested) ? $nested[0] : $nested;
if ($property === $nestedProperty) {
if ($this instanceof Swagger) {
$message = 'Required @' . str_replace('Swagger\\Annotations\\', 'SWG\\', $class) . '() not found';
} elseif (is_array($nested)) {
$message = $this->identity() . ' requires at least one @' . str_replace('Swagger\\Annotations\\', 'SWG\\', $class) . '() in ' . $this->_context;
} else {
$message = $this->identity() . ' requires a @' . str_replace('Swagger\\Annotations\\', 'SWG\\', $class) . '() in ' . $this->_context;
}
break;
}
}
Logger::notice($message);
}
}
}
// Report invalid types
foreach (static::$_types as $property => $type) {
$value = $this->{$property};
if ($value === null || $value === UNDEFINED) {
continue;
}
if (is_string($type)) {
if ($this->validateType($type, $value) === false) {
$valid = false;
Logger::notice($this->identity() . '->' . $property . ' is a "' . gettype($value) . '", expecting a "' . $type . '" in ' . $this->_context);
}
} elseif (is_array($type)) {
// enum?
if (in_array($value, $type) === false) {
Logger::notice($this->identity() . '->' . $property . ' "' . $value . '" is invalid, expecting "' . implode('", "', $type) . '" in ' . $this->_context);
}
} else {
throw new Exception('Invalid ' . get_class($this) . '::$_types[' . $property . ']');
}
}
$parents[] = $this;
return self::_validate($this, $parents, $skip) ? $valid : false;
}