Completed
Branch 2.0 (13ec26)
by Anton
05:17
created

RoadRunnerDispatcher::handleException()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 2
nc 3
nop 2
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\RoadRunner;
10
11
use Psr\Container\ContainerExceptionInterface;
12
use Psr\Container\ContainerInterface;
13
use Spiral\Boot\DispatcherInterface;
14
use Spiral\Boot\EnvironmentInterface;
15
use Spiral\Exceptions\HtmlHandler;
16
use Spiral\Goridge\StreamRelay;
17
use Spiral\Http\HttpCore;
18
use Spiral\Snapshots\SnapshotInterface;
19
use Spiral\Snapshots\SnapshotterInterface;
20
use Zend\Diactoros\Response;
21
22
class RoadRunnerDispatcher implements DispatcherInterface
23
{
24
    /** @var EnvironmentInterface */
25
    private $environment;
26
27
    /** @var ContainerInterface */
28
    private $container;
29
30
    /**
31
     * @var callable[]
32
     */
33
    private $finalizers = [];
34
35
    /**
36
     * @param EnvironmentInterface $environment
37
     * @param ContainerInterface   $container
38
     */
39
    public function __construct(EnvironmentInterface $environment, ContainerInterface $container)
40
    {
41
        $this->environment = $environment;
42
        $this->container = $container;
43
    }
44
45
    /**
46
     * Finalizers are executed after every request and used for garbage collection
47
     * or to close open connections.
48
     *
49
     * @param callable $finalizer
50
     */
51
    public function addFinalizer(callable $finalizer)
52
    {
53
        $this->finalizers[] = $finalizer;
54
    }
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public function canServe(): bool
60
    {
61
        return (php_sapi_name() == 'cli' && $this->environment->get('RR') !== null);
62
    }
63
64
    /**
65
     * @inheritdoc
66
     */
67
    public function serve()
68
    {
69
        /** @var HttpCore $http */
70
        $http = $this->container->get(HttpCore::class);
71
        $client = $this->psr7Client();
72
73
        while ($request = $client->acceptRequest()) {
74
            try {
75
                $client->respond($http->handle($request));
76
            } catch (\Throwable $e) {
77
                $this->handleException($client, $e);
78
            } finally {
79
                foreach ($this->finalizers as $finalizer) {
80
                    call_user_func($finalizer);
81
                }
82
            }
83
        }
84
    }
85
86
    /**
87
     * @return PSR7Client
88
     */
89
    protected function psr7Client(): PSR7Client
90
    {
91
        $worker = new Worker(new StreamRelay(STDIN, STDOUT));
0 ignored issues
show
Documentation introduced by
STDIN is of type string, but the function expects a resource.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
STDOUT is of type string, but the function expects a resource.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
92
93
        return new PSR7Client($worker);
94
    }
95
96
    /**
97
     * @param PSR7Client $client
98
     * @param \Throwable $e
99
     */
100
    protected function handleException(PSR7Client $client, \Throwable $e)
101
    {
102
        $handler = new HtmlHandler(HtmlHandler::INVERTED);
103
104
        try {
105
            /** @var SnapshotInterface $snapshot */
106
            $snapshot = $this->container->get(SnapshotterInterface::class)->register($e);
107
            error_log($snapshot->getMessage());
108
        } catch (\Throwable|ContainerExceptionInterface $se) {
109
            error_log($handler->getMessage($e));
110
        }
111
112
        // Reporting system (non handled) exception directly to the client
113
        $response = new Response('php://memory', 500);
114
        $response->getBody()->write(
115
            $handler->renderException($e, HtmlHandler::VERBOSITY_VERBOSE)
116
        );
117
118
        $client->respond($response);
119
    }
120
}