Passed
Push — master ( c62c90...75b396 )
by Anton
02:11
created

RrDispatcher::canServe()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Http;
13
14
use Psr\Container\ContainerExceptionInterface;
15
use Psr\Container\ContainerInterface;
16
use Psr\Http\Message\ResponseFactoryInterface;
17
use Spiral\Boot\DispatcherInterface;
18
use Spiral\Boot\EnvironmentInterface;
19
use Spiral\Boot\FinalizerInterface;
20
use Spiral\Core\FactoryInterface;
21
use Spiral\Debug\StateInterface;
22
use Spiral\Exceptions\HtmlHandler;
23
use Spiral\RoadRunner\PSR7Client;
24
use Spiral\Snapshots\SnapshotInterface;
25
use Spiral\Snapshots\SnapshotterInterface;
26
27
final class RrDispatcher implements DispatcherInterface
28
{
29
    /** @var EnvironmentInterface */
30
    private $env;
31
32
    /** @var FinalizerInterface */
33
    private $finalizer;
34
35
    /** @var ContainerInterface */
36
    private $container;
37
38
    /** @var FactoryInterface */
39
    private $factory;
40
41
    /**
42
     * @param EnvironmentInterface $env
43
     * @param FinalizerInterface   $finalizer
44
     * @param ContainerInterface   $container
45
     * @param FactoryInterface     $factory
46
     */
47
    public function __construct(
48
        EnvironmentInterface $env,
49
        FinalizerInterface $finalizer,
50
        ContainerInterface $container,
51
        FactoryInterface $factory
52
    ) {
53
        $this->env = $env;
54
        $this->finalizer = $finalizer;
55
        $this->container = $container;
56
        $this->factory = $factory;
57
    }
58
59
    /**
60
     * @inheritdoc
61
     */
62
    public function canServe(): bool
63
    {
64
        return (php_sapi_name() == 'cli' && $this->env->get('RR_HTTP') !== null);
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function serve(PSR7Client $client = null): void
71
    {
72
        // On demand to save some memory.
73
74
        $client = $client ?? $this->factory->make(PSR7Client::class);
75
76
        /** @var Http $http */
77
        $http = $this->container->get(Http::class);
78
        while ($request = $client->acceptRequest()) {
0 ignored issues
show
Bug introduced by
The method acceptRequest() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
        while ($request = $client->/** @scrutinizer ignore-call */ acceptRequest()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
79
            try {
80
                $client->respond($http->handle($request));
81
            } catch (\Throwable $e) {
82
                $this->handleException($client, $e);
0 ignored issues
show
Bug introduced by
It seems like $client can also be of type null; however, parameter $client of Spiral\Http\RrDispatcher::handleException() does only seem to accept Spiral\RoadRunner\PSR7Client, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
                $this->handleException(/** @scrutinizer ignore-type */ $client, $e);
Loading history...
83
            } finally {
84
                $this->finalizer->finalize(false);
85
            }
86
        }
87
    }
88
89
    /**
90
     * @param PSR7Client $client
91
     * @param \Throwable $e
92
     */
93
    protected function handleException(PSR7Client $client, \Throwable $e): void
94
    {
95
        $handler = new HtmlHandler();
96
97
        try {
98
            /** @var SnapshotInterface $snapshot */
99
            $snapshot = $this->container->get(SnapshotterInterface::class)->register($e);
100
            error_log($snapshot->getMessage());
101
102
            // on demand
103
            $state = $this->container->get(StateInterface::class);
104
            if ($state !== null) {
105
                $handler = $handler->withState($state);
106
            }
107
        } catch (\Throwable | ContainerExceptionInterface $se) {
108
            error_log((string)$e);
109
        }
110
111
        /** @var ResponseFactoryInterface $responseFactory */
112
        $responseFactory = $this->container->get(ResponseFactoryInterface::class);
113
        $response = $responseFactory->createResponse(500);
114
115
        // Reporting system (non handled) exception directly to the client
116
        $response->getBody()->write(
117
            $handler->renderException($e, HtmlHandler::VERBOSITY_VERBOSE)
118
        );
119
120
        $client->respond($response);
121
    }
122
}
123