Completed
Push — master ( ba7c5d...c3b626 )
by Julián
02:08
created

Render::__invoke()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 33
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 33
rs 8.439
cc 6
eloc 25
nc 10
nop 3
1
<?php
2
/**
3
 * Effortless maintenance management (http://juliangut.com/janitor)
4
 *
5
 * @link https://github.com/juliangut/janitor for the canonical source repository
6
 *
7
 * @license https://github.com/juliangut/janitor/blob/master/LICENSE
8
 */
9
10
namespace Janitor\Handler;
11
12
use Janitor\Handler as HandlerInterface;
13
use Janitor\Watcher;
14
use Janitor\ScheduledWatcher;
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Http\Message\ResponseInterface;
17
use Zend\Diactoros\Stream;
18
19
/**
20
 * Render HTML page maintenance handler.
21
 */
22
class Render implements HandlerInterface
23
{
24
    /**
25
     * Known handled content types.
26
     *
27
     * @var array
28
     */
29
    protected $knownContentTypes = [
30
        'application/json',
31
        'application/xml',
32
        'text/xml',
33
        'text/html',
34
    ];
35
36
    /**
37
     * {@inheritdoc}
38
     */
39
    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Watcher $watcher)
40
    {
41
        $content = '';
42
43
        $contentType = $this->determineContentType($request);
44
        switch ($contentType) {
45
            case 'application/json':
46
                $content = $this->renderJson($watcher);
47
                break;
48
            case 'text/xml':
49
            case 'application/xml':
50
                $content = $this->renderXml($watcher);
51
                break;
52
            case 'text/html':
53
                $content = $this->renderHtml($watcher);
54
                break;
55
        }
56
57
        $body = new Stream('php://temp', 'r+');
58
        $body->write($content);
59
60
        if ($watcher instanceof ScheduledWatcher) {
61
            $response = $response->withHeader('Expires', $watcher->getEnd()->format('D, d M Y H:i:s e'));
62
        } else {
63
            $response = $response->withHeader('Cache-Control', 'max-age=0')
64
                ->withHeader('Cache-Control', 'no-cache, must-revalidate')
65
                ->withHeader('Pragma', 'no-cache');
66
        }
67
68
        return $response->withStatus(503)
69
            ->withHeader('Content-Type', $contentType)
70
            ->withBody($body);
71
    }
72
73
    /**
74
     * Render HTML maintenance message.
75
     *
76
     * @param \Janitor\Watcher $watcher
77
     *
78
     * @return string
79
     */
80
    protected function renderHtml(Watcher $watcher)
81
    {
82
        $title = 'Maintenance';
83
        $message = $this->getMaintenanceMessage($watcher);
84
85
        return sprintf(
86
            "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
87
            "<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," .
88
            "sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{" .
89
            "display:inline-block;width:65px;}</style></head><body><h1>%s</h1>%s</body></html>",
90
            $title,
91
            $title,
92
            $message
93
        );
94
    }
95
96
    /**
97
     * Render JSON maintenance message.
98
     *
99
     * @param \Janitor\Watcher $watcher
100
     *
101
     * @return string
102
     */
103
    protected function renderJson(Watcher $watcher)
104
    {
105
        return json_encode(['message' => $this->getMaintenanceMessage($watcher)], JSON_PRETTY_PRINT);
106
    }
107
108
    /**
109
     * Render XML maintenance message.
110
     *
111
     * @param \Janitor\Watcher $watcher
112
     *
113
     * @return string
114
     */
115
    protected function renderXml(Watcher $watcher)
116
    {
117
        return sprintf(
118
            "<maintenance>\n  <message>%s</message>\n</maintenance>",
119
            $this->getMaintenanceMessage($watcher)
120
        );
121
    }
122
123
    /**
124
     * Retrieve custom maintenance message.
125
     *
126
     * @param \Janitor\Watcher $watcher
127
     *
128
     * @return string
129
     */
130
    protected function getMaintenanceMessage(Watcher $watcher)
131
    {
132
        $message = 'Maintenance mode is not active!';
133
        if ($watcher->isActive()) {
134
            $message = $watcher instanceof ScheduledWatcher
135
                ? 'Undergoing maintenance tasks until ' . $watcher->getEnd()->format('Y/m/d H:i:s')
136
                : 'Undergoing maintenance tasks';
137
        }
138
139
        return $message;
140
    }
141
142
    /**
143
     * Determine content type using Accept header.
144
     *
145
     * @param \Psr\Http\Message\ServerRequestInterface $request
146
     *
147
     * @return string
148
     */
149
    private function determineContentType(ServerRequestInterface $request)
150
    {
151
        $acceptHeader = $request->getHeaderLine('Accept');
152
        $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes);
153
        if (count($selectedContentTypes)) {
154
            return $selectedContentTypes[0];
155
        }
156
157
        return 'text/html';
158
    }
159
}
160