Skip to content

Commit 6d21f83

Browse files
a-barzantiPaul
authored and
Paul
committed
Added TryCatchStrategy and accompanying test and documentation.
1 parent f741e7c commit 6d21f83

File tree

3 files changed

+154
-3
lines changed

3 files changed

+154
-3
lines changed

README.md

+42-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ Contents
3434
10. [Merge](#merge)
3535
11. [TakeFirst](#takefirst)
3636
12. [ToList](#tolist)
37-
13. [Type](#type)
38-
14. [Unique](#unique)
39-
15. [Walk](#walk)
37+
13. [TryCatch](#trycatch)
38+
14. [Type](#type)
39+
15. [Unique](#unique)
40+
16. [Walk](#walk)
4041
5. [Requirements](#requirements)
4142
6. [Limitations](#limitations)
4243
7. [Testing](#testing)
@@ -649,6 +650,44 @@ ToList(Strategy|Mapping|array|mixed $expression)
649650

650651
> ['bar']
651652
653+
### TryCatch
654+
655+
Uses the handler callback to catch and manage any exception thrown by the primary strategy, if an exception was raised delegates to a fallback expression.
656+
657+
It is possible to use nested TryCatch strategies to manage different types of exceptions.
658+
659+
#### Signature
660+
661+
```php
662+
TryCatch(Strategy $strategy, callable $handler, Strategy|Mapping|array|mixed $expression)
663+
```
664+
665+
1. `$strategy` – Primary Strategy that might raise an exception.
666+
2. `$handler` – Handler function that receives the raised exception as its first argument.
667+
1. `$expression` – Expression.
668+
669+
#### Examples
670+
671+
```php
672+
(new Mapper)->map(
673+
[],
674+
new TryCatch(
675+
new Callback(
676+
function ($data, $context) {
677+
throw new \LogicException;
678+
}
679+
),
680+
function (\Exception $e) {
681+
if (! $e instanceof \LogicException) {
682+
throw $e;
683+
}
684+
},
685+
'LogicExceptionHandled'
686+
)
687+
);
688+
```
689+
> 'LogicExceptionHandled'
690+
652691
### Type
653692

654693
Casts data to the specified type.

src/Strategy/TryCatch.php

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
namespace ScriptFUSION\Mapper\Strategy;
3+
4+
use ScriptFUSION\Mapper\Mapping;
5+
6+
/**
7+
* TryCatch uses the handler callback to catch and manage any exception thrown by
8+
* the primary strategy, if an exception was raised delegates to a fallback expression.
9+
*/
10+
class TryCatch extends Decorator
11+
{
12+
private $expression;
13+
private $handler;
14+
15+
/**
16+
* @param Strategy $strategy
17+
* @param callable $handler
18+
* @param Strategy|Mapping|array|mixed $expression
19+
*/
20+
public function __construct(Strategy $strategy, callable $handler, $expression)
21+
{
22+
parent::__construct($strategy);
23+
24+
$this->handler = $handler;
25+
$this->expression = $expression;
26+
}
27+
28+
public function __invoke($data, $context = null)
29+
{
30+
try {
31+
return parent::__invoke($data, $context);
32+
} catch (\Exception $e) {
33+
call_user_func($this->handler, $e);
34+
35+
return $this->delegate($this->expression, $data, $context);
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
namespace ScriptFUSIONTest\Unit\Mapper\Strategy;
3+
4+
use ScriptFUSION\Mapper\Mapper;
5+
use ScriptFUSION\Mapper\Strategy\Callback;
6+
use ScriptFUSION\Mapper\Strategy\TryCatch;
7+
8+
final class TryCatchTest extends \PHPUnit_Framework_TestCase
9+
{
10+
private $callback;
11+
12+
protected function setUp()
13+
{
14+
$this->callback = new Callback(function ($data) {
15+
if ($data[0] === 'LogicError') {
16+
throw new \LogicException('Test Logic Exception');
17+
}
18+
if ($data[0] === 'DomainError') {
19+
throw new \DomainException('Test Domain Exception');
20+
}
21+
22+
return $data;
23+
});
24+
}
25+
26+
public function testTryCatch()
27+
{
28+
/** @var TryCatch $tryCatch */
29+
$tryCatch = (
30+
new TryCatch(
31+
$this->callback,
32+
function (\Exception $e) {
33+
if (! $e instanceof \DomainException) {
34+
throw $e;
35+
}
36+
},
37+
'ExceptionHandled'
38+
)
39+
)->setMapper(new Mapper);
40+
41+
self::assertSame(['foo', 'bar'], $tryCatch(['foo', 'bar']));
42+
self::assertSame('ExceptionHandled', $tryCatch(['DomainError', 'foo']));
43+
$this->setExpectedException(\LogicException::class);
44+
self::assertNotEquals('ExceptionHandled', $tryCatch(['LogicError', 'foo']));
45+
}
46+
47+
public function testMultipleTryCatch()
48+
{
49+
/** @var TryCatch $tryCatch */
50+
$tryCatch = (
51+
new TryCatch(
52+
new TryCatch(
53+
$this->callback,
54+
function (\Exception $e) {
55+
if (! $e instanceof \DomainException) {
56+
throw $e;
57+
}
58+
},
59+
'DomainExceptionHandled'
60+
),
61+
function (\Exception $e) {
62+
if (! $e instanceof \LogicException) {
63+
throw $e;
64+
}
65+
},
66+
'LogicExceptionHandled'
67+
)
68+
)->setMapper(new Mapper);
69+
70+
self::assertSame(['foo', 'bar'], $tryCatch(['foo', 'bar']));
71+
self::assertSame('LogicExceptionHandled', $tryCatch(['LogicError', 'foo']));
72+
self::assertSame('DomainExceptionHandled', $tryCatch(['DomainError', 'foo']));
73+
}
74+
}

0 commit comments

Comments
 (0)