Render   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 0
Metric Value
wmc 17
lcom 2
cbo 5
dl 0
loc 152
rs 10
c 0
b 0
f 0

6 Methods

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