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

HttpDispatcher::serve()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 2
nc 3
nop 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Http;
10
11
use Psr\Container\ContainerExceptionInterface;
12
use Psr\Container\ContainerInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
use Spiral\Boot\DispatcherInterface;
15
use Spiral\Boot\EnvironmentInterface;
16
use Spiral\Exceptions\HtmlHandler;
17
use Spiral\Snapshots\SnapshotInterface;
18
use Spiral\Snapshots\SnapshotterInterface;
19
use Zend\Diactoros\Response;
20
use Zend\Diactoros\ServerRequestFactory;
21
use Zend\HttpHandlerRunner\Emitter\EmitterInterface;
22
23
class HttpDispatcher implements DispatcherInterface
24
{
25
    /** @var EnvironmentInterface */
26
    private $environment;
27
28
    /** @var ContainerInterface */
29
    private $container;
30
31
    /**
32
     * @param EnvironmentInterface $environment
33
     * @param ContainerInterface   $container
34
     */
35
    public function __construct(EnvironmentInterface $environment, ContainerInterface $container)
36
    {
37
        $this->environment = $environment;
38
        $this->container = $container;
39
    }
40
41
    /**
42
     * @inheritdoc
43
     */
44
    public function canServe(): bool
45
    {
46
        return php_sapi_name() != 'cli';
47
    }
48
49
    /**
50
     * @inheritdoc
51
     */
52
    public function serve()
53
    {
54
        /**
55
         * @var HttpCore         $http
56
         * @var EmitterInterface $emitter
57
         */
58
        $http = $this->container->get(HttpCore::class);
59
        $emitter = $this->container->get(EmitterInterface::class);
60
61
        try {
62
            $response = $http->handle($this->initRequest());
63
            $emitter->emit($response);
64
        } catch (\Throwable $e) {
65
            $this->handleException($emitter, $e);
66
        }
67
    }
68
69
    /**
70
     * @inheritdoc
71
     */
72
    protected function initRequest(): ServerRequestInterface
73
    {
74
        return ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
75
    }
76
77
    /**
78
     * @param EmitterInterface $emitter
79
     * @param \Throwable       $e
80
     */
81
    protected function handleException(EmitterInterface $emitter, \Throwable $e)
82
    {
83
        $handler = new HtmlHandler(HtmlHandler::INVERTED);
84
85
        try {
86
            /** @var SnapshotInterface $snapshot */
87
            $this->container->get(SnapshotterInterface::class)->register($e);
88
        } catch (\Throwable|ContainerExceptionInterface $se) {
89
            // nothing to report
90
        }
91
92
        // Reporting system (non handled) exception directly to the client
93
        $response = new Response('php://memory', 500);
94
        $response->getBody()->write(
95
            $handler->renderException($e, HtmlHandler::VERBOSITY_VERBOSE)
96
        );
97
98
        $emitter->emit($response);
99
    }
100
}