modifs.mineures sans commentaires
This commit is contained in:
parent
8cf225ea1e
commit
43b7b046fa
|
@ -0,0 +1,101 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ExceptionShadow: une classe qui capture les informations d'une
|
||||||
|
* exception afin de pouvoir les sérialiser
|
||||||
|
*/
|
||||||
|
class ExceptionShadow {
|
||||||
|
protected static function extract_trace(array $trace): array {
|
||||||
|
$frames = [];
|
||||||
|
foreach ($trace as $frame) {
|
||||||
|
$file = cl::get($frame, "file");
|
||||||
|
$line = cl::get($frame, "line");
|
||||||
|
$class = cl::get($frame, "class");
|
||||||
|
$function = cl::get($frame, "function");
|
||||||
|
$type = cl::get($frame, "type");
|
||||||
|
$frames[] = [
|
||||||
|
"file" => $file,
|
||||||
|
"line" => $line,
|
||||||
|
"class" => $class,
|
||||||
|
"object" => null,
|
||||||
|
"type" => $type,
|
||||||
|
"function" => $function,
|
||||||
|
"args" => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __construct(Throwable $exception) {
|
||||||
|
$this->class = get_class($exception);
|
||||||
|
$this->message = $exception->getMessage();
|
||||||
|
$this->code = $exception->getCode();
|
||||||
|
$this->file = $exception->getFile();
|
||||||
|
$this->line = $exception->getLine();
|
||||||
|
$this->trace = self::extract_trace($exception->getTrace());
|
||||||
|
$previous = $exception->getPrevious();
|
||||||
|
if ($previous !== null) $this->previous = new static($previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $class;
|
||||||
|
|
||||||
|
function getClass(): string {
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $message;
|
||||||
|
|
||||||
|
function getMessage(): string {
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var mixed */
|
||||||
|
protected $code;
|
||||||
|
|
||||||
|
function getCode() {
|
||||||
|
return $this->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $file;
|
||||||
|
|
||||||
|
function getFile(): string {
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $line;
|
||||||
|
|
||||||
|
function getLine(): int {
|
||||||
|
return $this->line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
protected $trace;
|
||||||
|
|
||||||
|
function getTrace(): array {
|
||||||
|
return $this->trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTraceAsString(): string {
|
||||||
|
$lines = [];
|
||||||
|
foreach ($this->trace as $index => $frame) {
|
||||||
|
$lines[] = "#$index $frame[file]($frame[line]): $frame[class]$frame[type]$frame[function]()";
|
||||||
|
}
|
||||||
|
$index++;
|
||||||
|
$lines[] = "#$index {main}";
|
||||||
|
return implode("\n", $lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var ExceptionShadow */
|
||||||
|
protected $previous;
|
||||||
|
|
||||||
|
function getPrevious(): ?ExceptionShadow {
|
||||||
|
return $this->previous;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ExitException: une exception qui indique que l'application souhaite
|
||||||
|
* quitter normalement, avec éventuellement un code d'erreur.
|
||||||
|
*/
|
||||||
|
class ExitException extends UserException {
|
||||||
|
function __construct(int $exitcode=0, $user_message=null, Throwable $previous=null) {
|
||||||
|
parent::__construct($user_message, null, $exitcode, $previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isError(): bool {
|
||||||
|
return $this->getCode() !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function haveMessage(): bool {
|
||||||
|
return $this->getUserMessage() !== null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class StopException: une exception qui par convention est envoyée à un
|
||||||
|
* générateur pour indiquer qu'il doit s'arrêter "proprement". cela peut être
|
||||||
|
* utilisé pour implémenter des itérateur "closeable"
|
||||||
|
*/
|
||||||
|
class StopException extends Exception {
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
namespace nulib;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserException: une exception qui peut en plus contenir un message
|
||||||
|
* utilisateur
|
||||||
|
*/
|
||||||
|
class UserException extends Exception {
|
||||||
|
/** @param Throwable|ExceptionShadow $e */
|
||||||
|
static function get_user_message($e): ?string {
|
||||||
|
if ($e instanceof self) return $e->getUserMessage();
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Throwable|ExceptionShadow $e */
|
||||||
|
static final function get_user_summary($e): string {
|
||||||
|
$parts = [];
|
||||||
|
$first = true;
|
||||||
|
while ($e !== null) {
|
||||||
|
$message = self::get_user_message($e);
|
||||||
|
if (!$message) $message = "(no message)";
|
||||||
|
if ($first) $first = false;
|
||||||
|
else $parts[] = "caused by ";
|
||||||
|
$parts[] = get_class($e) . ": " . $message;
|
||||||
|
$e = $e->getPrevious();
|
||||||
|
}
|
||||||
|
return implode(", ", $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Throwable|ExceptionShadow $e */
|
||||||
|
static function get_message($e): ?string {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
if (!$message && $e instanceof self) $message = $e->getUserMessage();
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Throwable|ExceptionShadow $e */
|
||||||
|
static final function get_summary($e): string {
|
||||||
|
$parts = [];
|
||||||
|
$first = true;
|
||||||
|
while ($e !== null) {
|
||||||
|
$message = self::get_message($e);
|
||||||
|
if (!$message) $message = "(no message)";
|
||||||
|
if ($first) $first = false;
|
||||||
|
else $parts[] = "caused by ";
|
||||||
|
if ($e instanceof ExceptionShadow) $class = $e->getClass();
|
||||||
|
else $class = get_class($e);
|
||||||
|
$parts[] = "$class: $message";
|
||||||
|
$e = $e->getPrevious();
|
||||||
|
}
|
||||||
|
return implode(", ", $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Throwable|ExceptionShadow $e */
|
||||||
|
static final function get_traceback($e): string {
|
||||||
|
$tbs = [];
|
||||||
|
$previous = false;
|
||||||
|
while ($e !== null) {
|
||||||
|
if (!$previous) {
|
||||||
|
$efile = $e->getFile();
|
||||||
|
$eline = $e->getLine();
|
||||||
|
$tbs[] = "at $efile($eline)";
|
||||||
|
} else {
|
||||||
|
$tbs[] = "~~ caused by: " . self::get_summary($e);
|
||||||
|
}
|
||||||
|
$tbs[] = $e->getTraceAsString();
|
||||||
|
$e = $e->getPrevious();
|
||||||
|
$previous = true;
|
||||||
|
#XXX il faudrait ne pas réinclure les lignes communes aux exceptions qui
|
||||||
|
# ont déjà été affichées
|
||||||
|
}
|
||||||
|
return implode("\n", $tbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function __construct($user_message, $tech_message=null, $code=0, ?Throwable $previous=null) {
|
||||||
|
$this->userMessage = $user_message;
|
||||||
|
if ($tech_message === null) $tech_message = $user_message;
|
||||||
|
parent::__construct($tech_message, $code, $previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $userMessage;
|
||||||
|
|
||||||
|
function getUserMessage(): ?string {
|
||||||
|
return $this->userMessage;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
namespace nulib;
|
namespace nulib;
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ValueException: indiquer qu'une valeur est invalide
|
* Class ValueException: indiquer qu'une valeur est invalide
|
||||||
*/
|
*/
|
||||||
class ValueException extends Exception {
|
class ValueException extends UserException {
|
||||||
private static function value($value): string {
|
private static function value($value): string {
|
||||||
if (is_object($value)) {
|
if (is_object($value)) {
|
||||||
return "<".get_class($value).">";
|
return "<".get_class($value).">";
|
||||||
|
@ -40,11 +38,23 @@ class ValueException extends Exception {
|
||||||
return new static(self::message(null, $message, $kind, $prefix, " is null"));
|
return new static(self::message(null, $message, $kind, $prefix, " is null"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static final function invalid($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self {
|
static final function invalid_kind($value=null, ?string $kind=null, ?string $prefix=null, ?string $message=null): self {
|
||||||
return new static(self::message($value, $message, $kind, $prefix, " is invalid"));
|
return new static(self::message($value, $message, $kind, $prefix, " is invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static final function unexpected_class($class, string $expected_class) {
|
static final function invalid_key($value, ?string $prefix=null, ?string $message=null): self {
|
||||||
|
return self::invalid_kind($value, "key", $prefix, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function invalid_value($value, ?string $prefix=null, ?string $message=null): self {
|
||||||
|
return self::invalid_kind($value, "value", $prefix, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function invalid_type($value, string $expected_type): self {
|
||||||
|
return new static(self::message($value, null, "type", null, " is invalid, expected $expected_type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static final function invalid_class($class, string $expected_class): self {
|
||||||
if (is_object($class)) $class = get_class($class);
|
if (is_object($class)) $class = get_class($class);
|
||||||
return new static(self::message($class, null, "class", null, " is invalid, expected $expected_class"));
|
return new static(self::message($class, null, "class", null, " is invalid, expected $expected_class"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ class cv {
|
||||||
$index = is_int($value)? $value : null;
|
$index = is_int($value)? $value : null;
|
||||||
$key = is_string($value)? $value : null;
|
$key = is_string($value)? $value : null;
|
||||||
if ($index === null && $key === null && $throw_exception) {
|
if ($index === null && $key === null && $throw_exception) {
|
||||||
throw ValueException::invalid($value, "key", $prefix);
|
throw ValueException::invalid_kind($value, "key", $prefix);
|
||||||
} else {
|
} else {
|
||||||
return [$index, $key];
|
return [$index, $key];
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ class cv {
|
||||||
$string = is_string($value)? $value : null;
|
$string = is_string($value)? $value : null;
|
||||||
$array = is_array($value)? $value : null;
|
$array = is_array($value)? $value : null;
|
||||||
if ($bool === null && $string === null && $array === null && $throw_exception) {
|
if ($bool === null && $string === null && $array === null && $throw_exception) {
|
||||||
throw ValueException::invalid($value, "value", $prefix);
|
throw ValueException::invalid_kind($value, "value", $prefix);
|
||||||
} else {
|
} else {
|
||||||
return [$bool, $string, $array];
|
return [$bool, $string, $array];
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,7 @@ class str {
|
||||||
} elseif (preg_match(self::CAMEL_PATTERN2, $camel, $vs, PREG_OFFSET_CAPTURE)) {
|
} elseif (preg_match(self::CAMEL_PATTERN2, $camel, $vs, PREG_OFFSET_CAPTURE)) {
|
||||||
# préfixe en minuscule
|
# préfixe en minuscule
|
||||||
} else {
|
} else {
|
||||||
throw ValueException::invalid($camel, "camel string");
|
throw ValueException::invalid_kind($camel, "camel string");
|
||||||
}
|
}
|
||||||
$parts[] = strtolower($vs[1][0]);
|
$parts[] = strtolower($vs[1][0]);
|
||||||
$index = intval($vs[1][1]) + strlen($vs[1][0]);
|
$index = intval($vs[1][1]) + strlen($vs[1][0]);
|
||||||
|
|
|
@ -4,11 +4,11 @@ namespace nulib;
|
||||||
use nulib\tests\TestCase;
|
use nulib\tests\TestCase;
|
||||||
|
|
||||||
class ValueExceptionTest extends TestCase {
|
class ValueExceptionTest extends TestCase {
|
||||||
function testUnexpectedClass() {
|
function testInvalidClass() {
|
||||||
$e = ValueException::unexpected_class(null, self::class);
|
$e = ValueException::invalid_class(null, self::class);
|
||||||
self::assertSame("class is invalid, expected ".self::class, $e->getMessage());
|
self::assertSame("class is invalid, expected ".self::class, $e->getMessage());
|
||||||
|
|
||||||
$e = ValueException::unexpected_class(ValueException::class, self::class);
|
$e = ValueException::invalid_class(ValueException::class, self::class);
|
||||||
self::assertSame(ValueException::class.": class is invalid, expected ".self::class, $e->getMessage());
|
self::assertSame(ValueException::class.": class is invalid, expected ".self::class, $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue