Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 5 #36

Merged
merged 13 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
composer.lock
vendor/*
.phpunit.result.cache
.phpunit.cache/*
5 changes: 3 additions & 2 deletions .phan/config.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

return [
'directory_list' => ['src', 'vendor'],
'exclude_analysis_directory_list' => ['vendor']
"directory_list" => ["src", "vendor"],
"exclude_analysis_directory_list" => ["vendor"],
"exclude_file_list" => ["vendor/php-enspired/peekaboo/stubs/exceptable.php"]
];
124 changes: 88 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![](https://img.shields.io/github/release/php-enspired/exceptable.svg) ![](https://img.shields.io/badge/PHP-7.4-blue.svg?colorB=8892BF) ![](https://img.shields.io/badge/PHP-8-blue.svg?colorB=8892BF) ![](https://img.shields.io/badge/license-GPL_3.0_only-blue.svg)
![](https://img.shields.io/github/release/php-enspired/exceptable.svg) ![](https://img.shields.io/badge/PHP-8.2-blue.svg?colorB=8892BF) ![](https://img.shields.io/badge/PHP-8-blue.svg?colorB=8892BF) ![](https://img.shields.io/badge/license-GPL_3.0_only-blue.svg)

how exceptable!
===============
Expand All @@ -10,7 +10,7 @@ Exceptables are easy to create and pass details to, they provide access to error
dependencies
------------

Requires php 7.4 or later.
Requires php 8.2 or later.

ICU support requires the `intl` extension.

Expand All @@ -24,58 +24,110 @@ a quick taste
```php
<?php

use AT\Exceptable\Handler;
use AT\Exceptable\Spl\RuntimeException;
use at\exceptable\ {
Error,
Handler\ExceptionHandler,
Handler\Handler,
IsError
};

// a simple Exceptable just for you
class FooException extends RuntimeException {
// a simple Error, just for you
enum FooError : int implements Error {
use IsError;

const UNKNOWN_FOO = 1;

const INFO = [
self::UNKNOWN_FOO => [
'message' => 'unknown foo',
'format' => "i don't know who, you think is foo, but it's not {foo}"
]
case UnknownFoo = 1;
public const MESSAGES = [
self::UnknownFoo->name => "i don't know who, you think is foo, but it's not {foo}"
];
}

throw new FooException(FooException::UNKNOWN_FOO);
(FooError::UnknownFoo)(["foo" => "foobedobedoo"]);
// on your screen:
// Fatal error: Uncaught FooException: unknown foo in ...
// Fatal error: Uncaught at\exceptable\Spl\RuntimeException: i don't know who, you think is foo, but it's not foobedobedoo

$handler = new Handler();
$handler
->onException(function($e) { error_log($e->getMessage()); return true; })
->register();

$context = ['foo' => 'foobedobedoo'];
throw new FooException(FooException::UNKNOWN_FOO, $context);
$handler->onException(new class() implements ExceptionHandler {
public function run(Throwable $t) {
error_log($t->getMessage());
return true;
}
});
$handler->register();

(FooError::UnknownFoo)(["foo" => "foobedobedoo"]);
// in your error log:
// i don't know who, you think is foo, but it's not foobedobedoo
```

errors as values
----------------

Having errors available to your application as normal values also makes _not_ throwing exceptions a viable solution. The _Result pattern_, for example, is a functional programming approach to error handling that treats error conditions as normal, expected return values. This can encourage you to consider how to handle error cases more carefully and closer to their source, as well as being a benefit to static analysis and comprehensibility in general. See [Larry Garfield's excellent article](https://peakd.com/hive-168588/@crell/much-ado-about-null) for more.

```php
<?php

use at\exceptable\ {
Error,
IsError
};

enum FooError : int implements Error {
use IsError;

case TheyToldMeToDoIt = 1;
public const MESSAGES = [
self::TheyToldMeToDoIt->name => "ooh noooooooooooooooooo!"
];
}

function foo(bool $fail) : string|FooError {
return $fail ?
FooError::TheyToldMeToDoIt :
"woooooooooooooooooo hoo!";
}

$bool = maybeTrueMaybeFalse();
$result = foo($bool);
if ($result instanceof FooError) {
echo $result->message();
// outputs "ooh noooooooooooooooooo!"

$bool = ! $bool;
$result = foo($bool);
}

echo $result;
// outputs "woooooooooooooooooo hoo!"
```
...and if you want to make _everybody_ mad, you can still throw them.
```php
throw $result(["yes" => "i know i'm horrible"]);
```

see more in [the wiki](https://github.com/php-enspired/exceptable/wiki).

Version 4.0 is here!
--------------------
Version 5.0
-----------

**Version 4.0** requires PHP 7.4 or greater.
- PHP 7.4 added typehints to some Throwable properties, which required changes to the `IsExceptable` trait. This means _Exceptable_ can no longer support PHP 7.3 or earlier - though that's fine, right? You've already upgraded your application to 8+ anyway, right?
- right?
**Version 5** requires PHP 8.2 or greater.
- ICU messaging system overhauled and published to its own package!
Check out [php-enspired/peekaboo](https://packagist.org/packages/php-enspired/peekaboo) - using _exceptable_ means you get it for free, so take advantage!
- Introduces the _Error_ interface for enums, making errors into first-class citizens and opening up the ability to handle errors as values.
Adds an `SplError` enum for php's built-in exception types.
- Reworks and improves functionality for Exceptables and the Handler.
Error / Exception / Shutdown Handlers now have explicit interfaces, as do debug log entries.

Version 3.0 is here!
--------------------
[Read the release notes.](https://github.com/php-enspired/exceptable/wiki/new-in-5.0)

**Version 3.0** requires PHP 7.3 or greater and introduces some exciting changes from version 2:
- Support* for ICU locales, message formats, and resource bundles!\
\* _requires the intl extension._
- Ready-to-extend (or just use) `Exceptable` classes based on the built-in SPL Exception classes!
- The generic `Exceptable` Exception base class has been removed.
- Introduces a "debug mode" for Handlers!
- Handlers are now Logger (e.g., Monolog)-aware!
Version 4.0
-----------

[Read more about the 3.0 release](https://github.com/php-enspired/exceptable/wiki/new-in-3.0).
**Version 4.0** requires PHP 7.4 or greater.
- PHP 7.4 added typehints to some Throwable properties, which required changes to the `IsExceptable` trait.
This means _Exceptable_ can no longer support PHP 7.3 or earlier - though that's fine, right?
You've already upgraded your application to 8+ anyway, right?
- right?

docs
----
Expand Down
15 changes: 8 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@
"source": "https://github.com/php-enspired/exceptable"
},
"require": {
"php": "^7.4 || ^8"
"php": "^8.2",
"php-enspired/peekaboo": "^1"
},
"suggest": {
"ext-intl": "Adds support for localization and ICU message formatting."
"ext-intl": "support for localization and full ICU message formatting features"
},
"require-dev": {
"phan/phan": "^5",
"phpunit/phpunit": "^9"
"phan/phan": "^5.4.3",
"phpunit/phpunit": "^10"
},
"autoload": {
"psr-4": {
"AT\\Exceptable\\": "src/",
"AT\\Exceptable\\Tests\\": "tests/"
"at\\exceptable\\": "src/",
"at\\exceptable\\Tests\\": "tests/"
}
},
"scripts": {
"build:dist": "bin/build-dist",
"build:locales": "genrb resources/language/*.txt -d resources/language/",
"build:test": "bin/build-test",
"test:phan": "vendor/bin/phan",
"test:analyze": "vendor/bin/phan",
"test:unit" : "vendor/bin/phpunit tests",
"wiki:update": "git subtree push --prefix docs wiki master",
"wiki:update-docs": "git subtree pull --prefix docs wiki master --squash --message='Merge wiki updates into docs'"
Expand Down
8 changes: 4 additions & 4 deletions docs/API:-The-Exceptable-Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ parameters:
- int **`$code`**
The exceptable code to look up

**throws** `at\exceptable\ExceptableException` if the code is not known to the implementation.
**throws** `at\exceptable\ExceptableError` if the code is not known to the implementation.

**returns** an array with info about the code, including (at a minimum) its `"code"` and `"message"`.

Expand Down Expand Up @@ -70,7 +70,7 @@ parameters:
- Throwable **`$previous`**
The previous Exception, if any.

**throws** `at\exceptable\ExceptableException` if the given code is invalid.
**throws** `at\exceptable\ExceptableError` if the given code is invalid.

**returns** a new Exceptable instance on success.

Expand All @@ -93,7 +93,7 @@ parameters:

**throws** `at\exceptable\Exceptable` on success.

**throws** `at\exceptable\ExceptableException` if the given code is invalid.
**throws** `at\exceptable\ExceptableError` if the given code is invalid.

---

Expand All @@ -117,7 +117,7 @@ parameters:
- Throwable **`$previous`**
The previous Exception, if any.

**throws** `at\exceptable\ExceptableException` if the given code is invalid.
**throws** `at\exceptable\ExceptableError` if the given code is invalid.

---

Expand Down
10 changes: 5 additions & 5 deletions docs/API:-The-ExceptableException-Class.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
`at\exceptable\ExceptableException`
`at\exceptable\ExceptableError`
===================================

Represents Exceptable error cases.

constants
---------

### ExceptableException::NO_SUCH_CODE
### ExceptableError::NO_SUCH_CODE
An invalid code was provided to an Exceptable class.

### ExceptableException::UNCAUGHT_EXCEPTION
### ExceptableError::UNCAUGHT_EXCEPTION
An exception was thrown which no registered exception handlers successfully handled.

### ExceptableException::INVALID_HANDLER
A handler threw an exception, had a bad signature, or had an invalid return value.
### ExceptableError::INVALID_HANDLER
A handler threw an exception, had a bad signature, or had an invalid return value.
2 changes: 1 addition & 1 deletion docs/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ docs
- [The Exceptable Interface](https://github.com/php-enspired/exceptable/wiki/API:-The-Exceptable-Interface)
- [The Exception Class](https://github.com/php-enspired/exceptable/wiki/API:-The-Exception-Class)
- [The Handler Class](https://github.com/php-enspired/exceptable/wiki/API:-The-Handler-Class)
- [The ExceptableException Class](https://github.com/php-enspired/exceptable/wiki/API:-The-ExceptableException-Class)
- [The ExceptableError Class](https://github.com/php-enspired/exceptable/wiki/API:-The-ExceptableError-Class)
- [Basic Exceptable Usage](https://github.com/php-enspired/exceptable/wiki/Usage:-Exceptables)
- [Basic Handler Usage](https://github.com/php-enspired/exceptable/wiki/Usage:-Handlers)

Expand Down
14 changes: 6 additions & 8 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="./vendor/autoload.php"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
colors="true">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
colors="true"
cacheDirectory=".phpunit.cache">

</phpunit>
Binary file removed resources/language/ko_KR.res
Binary file not shown.
10 changes: 0 additions & 10 deletions resources/language/ko_KR.txt

This file was deleted.

Binary file modified resources/language/root.res
Binary file not shown.
32 changes: 20 additions & 12 deletions resources/language/root.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
root {
exceptable {
exceptableexception {
invalid_handler { "Invalid handler [{type}]: {__rootMessage__}" }
no_such_code { "No exception code '{code}' is known" }
uncaught_exception { "No registered handler caught exception: {__rootMessage__}" }
}
tests {
testexceptable {
unknownfoo { "i don't know who, you think is foo, but it's not {foo}" }
toomuchfoo { "too much foo is bad for you (got {count,spellout} foo)" }
}
}
"at\exceptable\ExceptableError" {
UnknownError { "{__rootMessage__}" }
UnacceptableError { "Invalid Error type ''{type}'' (expected enum implementing at\exceptable\Error)" }
UncaughtException { "Uncaught Exception ({__rootType__}): {__rootMessage__}" }
HandlerFailed { "ExceptionHandler ({type}) failed: {__rootMessage__}" }
}
"at\exceptable\Spl\SplError" {
BadFunctionCall { "{__rootMessage__}" }
BadMethodCall { "{__rootMessage__}" }
Domain { "{__rootMessage__}" }
InvalidArgument { "{__rootMessage__}" }
Length { "{__rootMessage__}" }
Logic { "{__rootMessage__}" }
OutOfBounds { "{__rootMessage__}" }
OutOfRange { "{__rootMessage__}" }
Overflow { "{__rootMessage__}" }
Range { "{__rootMessage__}" }
Runtime { "{__rootMessage__}" }
Underflow { "{__rootMessage__}" }
UnexpectedValue { "{__rootMessage__}" }
}
}
Loading