1) { throw new self("${prefix}more than one $kind was found"); } else { throw new self("${prefix}unable to find any $kind"); } } static final function get_value_msg($value): string { if (is_object($value)) { return "object(".get_class($value).")"; } elseif (is_array($value)) { $values = $value; $parts = []; foreach ($values as $value) { $parts[] = self::get_value_msg($value); } return "array(".implode(", ", $parts).")"; } else { return var_export($value, true); } } static final function get_invalid_value_msg($value, string $kind="value", ?string $prefix=null): string { $msg = self::get_value_msg($value).": invalid $kind"; if ($prefix) $msg = "$prefix: $msg"; return $msg; } static final function invalid_value($value, string $kind="value", ?string $prefix=null): ValueException { return new self(self::get_invalid_value_msg($value, $kind, $prefix)); } static final function get_unexpected_value_msg($value, ?array $allowed_values=null, string $kind="value", ?string $prefix=null): string { $msg = "unexpected $kind"; if ($allowed_values !== null) { $msg .= ": must be one of ".self::get_value_msg($allowed_values); } if ($value !== null) $msg = self::get_value_msg($value).": $msg"; if ($prefix) $msg = "$prefix: $msg"; return $msg; } static final function unexpected_value($value, ?array $allowed_values=null, string $kind="value", ?string $prefix=null): ValueException { return new self(self::get_unexpected_value_msg($value, $allowed_values, $kind, $prefix)); } static final function get_unexpected_type_msg($expected_type, $value=null, ?string $prefix=null): string { $msg = "expected a value "; if (is_array($expected_type)) { $msg .= "of a type among (".implode(", ", $expected_type).")"; } else { $msg .= "of type $expected_type"; } if ($value !== null) { $msg .= ", got "; $msg .= self::get_value_msg($value); } else { $msg .= ", got null"; } if ($prefix) $msg = "$prefix: $msg"; return $msg; } static final function unexpected_type($expected_type, $value=null, ?string $prefix=null): ValueException { return new self(self::get_unexpected_type_msg($expected_type, $value, $prefix)); } static final function get_unexpected_class_msg($expected_class, $actual_class=null, ?string $prefix=null): string { $msg = "expected "; if (is_array($expected_class)) { $msg .= "one of (".implode(", ", $expected_class).")"; } else { $msg .= $expected_class; } if ($actual_class !== null) { $msg .= ", got "; $msg .= self::get_value_msg($actual_class); } if ($prefix) $msg = "$prefix: $msg"; return $msg; } static final function unexpected_class($expected_class, $actual_class=null, ?string $prefix=null): ValueException { return new self(self::get_unexpected_class_msg($expected_class, $actual_class, $prefix)); } static final function check_class($class, $expected_class, ?string $prefix=null): void { if (is_object($class)) $class = get_class($class); $found = false; foreach (A::with($expected_class) as $ec) { if ($class === $ec || is_subclass_of($class, $ec)) { $found = true; break; } } if (!$found) { throw self::unexpected_class($expected_class, $class, $prefix); } } }