Passed
Push — master ( 7af1bf...430d6b )
by
unknown
13:07
created

FileDeclaration::withHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Install\SystemEnvironment\ServerResponse;
19
20
use Psr\Http\Message\ResponseInterface;
21
22
/**
23
 * Declares contents on server response expectations on a static file.
24
 *
25
 * @internal should only be used from within TYPO3 Core
26
 */
27
class FileDeclaration
28
{
29
    public const FLAG_BUILD_HTML = 1;
30
    public const FLAG_BUILD_PHP = 2;
31
    public const FLAG_BUILD_SVG = 4;
32
    public const FLAG_BUILD_HTML_DOCUMENT = 64;
33
    public const FLAG_BUILD_SVG_DOCUMENT = 128;
34
35
    /**
36
     * @var FileLocation
37
     */
38
    protected $fileLocation;
39
40
    /**
41
     * @var string
42
     */
43
    protected $fileName;
44
45
    /**
46
     * @var bool
47
     */
48
    protected $fail;
49
50
    /**
51
     * @var string|null
52
     */
53
    protected $expectedContentType;
54
55
    /**
56
     * @var string|null
57
     */
58
    protected $unexpectedContentType;
59
60
    /**
61
     * @var string|null
62
     */
63
    protected $expectedContent;
64
65
    /**
66
     * @var string|null
67
     */
68
    protected $unexpectedContent;
69
70
    /**
71
     * @var \Closure
72
     */
73
    protected $handler;
74
75
    /**
76
     * @var int
77
     */
78
    protected $buildFlags = self::FLAG_BUILD_HTML | self::FLAG_BUILD_HTML_DOCUMENT;
79
80
    public function __construct(FileLocation $fileLocation, string $fileName, bool $fail = false)
81
    {
82
        $this->fileLocation = $fileLocation;
83
        $this->fileName = $fileName;
84
        $this->fail = $fail;
85
    }
86
87
    public function buildContent(): string
88
    {
89
        $content = '';
90
        if ($this->buildFlags & self::FLAG_BUILD_HTML) {
91
            $content .= '<div>HTML content</div>';
92
        }
93
        if ($this->buildFlags & self::FLAG_BUILD_PHP) {
94
            // base64 encoded representation of 'PHP content'
95
            $content .= '<div><?php echo base64_decode(\'UEhQIGNvbnRlbnQ=\');?></div>';
96
        }
97
        if ($this->buildFlags & self::FLAG_BUILD_SVG) {
98
            $content .= '<text id="test" x="0" y="0">SVG content</text>';
99
        }
100
        if ($this->buildFlags & self::FLAG_BUILD_SVG_DOCUMENT) {
101
            return sprintf(
102
                '<svg xmlns="http://www.w3.org/2000/svg">%s</svg>',
103
                $content
104
            );
105
        }
106
        return sprintf(
107
            '<!DOCTYPE html><html lang="en"><body>%s</body></html>',
108
            $content
109
        );
110
    }
111
112
    public function matches(ResponseInterface $response): bool
113
    {
114
        return $this->getMismatches($response) === [];
115
    }
116
117
    /**
118
     * @param ResponseInterface $response
119
     * @return StatusMessage[]
120
     */
121
    public function getMismatches(ResponseInterface $response): array
122
    {
123
        $mismatches = [];
124
        if ($this->handler instanceof \Closure) {
0 ignored issues
show
introduced by
$this->handler is always a sub-type of Closure.
Loading history...
125
            $result = $this->handler->call($this, $response);
126
            if ($result !== null) {
127
                $mismatches[] = $result;
128
            }
129
            return $mismatches;
130
        }
131
132
        $body = (string)$response->getBody();
133
        $contentType = $response->getHeaderLine('content-type');
134
        if ($this->expectedContent !== null && strpos($body, $this->expectedContent) === false) {
135
            $mismatches[] = new StatusMessage(
136
                'content mismatch %s',
137
                $this->expectedContent,
138
                $body
139
            );
140
        }
141
        if ($this->unexpectedContent !== null && strpos($body, $this->unexpectedContent) !== false) {
142
            $mismatches[] = new StatusMessage(
143
                'unexpected content %s',
144
                $this->unexpectedContent,
145
                $body
146
            );
147
        }
148
        if ($this->expectedContentType !== null
149
            && strpos($contentType . ';', $this->expectedContentType . ';') !== 0) {
150
            $mismatches[] = new StatusMessage(
151
                'content-type mismatch %s, got %s',
152
                $this->expectedContentType,
153
                $contentType
154
            );
155
        }
156
        if ($this->unexpectedContentType !== null
157
            && strpos($contentType . ';', $this->unexpectedContentType . ';') === 0) {
158
            $mismatches[] = new StatusMessage(
159
                'unexpected content-type %s',
160
                $this->unexpectedContentType,
161
                $contentType
162
            );
163
        }
164
        return $mismatches;
165
    }
166
167
    public function withExpectedContentType(string $contentType): self
168
    {
169
        $target = clone $this;
170
        $target->expectedContentType = $contentType;
171
        return $target;
172
    }
173
174
    public function withUnexpectedContentType(string $contentType): self
175
    {
176
        $target = clone $this;
177
        $target->unexpectedContentType = $contentType;
178
        return $target;
179
    }
180
181
    public function withExpectedContent(string $content): self
182
    {
183
        $target = clone $this;
184
        $target->expectedContent = $content;
185
        return $target;
186
    }
187
188
    public function withUnexpectedContent(string $content): self
189
    {
190
        $target = clone $this;
191
        $target->unexpectedContent = $content;
192
        return $target;
193
    }
194
195
    public function withHandler(\Closure $handler): self
196
    {
197
        $target = clone $this;
198
        $target->handler = $handler;
199
        return $target;
200
    }
201
202
    public function withBuildFlags(int $buildFlags): self
203
    {
204
        $target = clone $this;
205
        $target->buildFlags = $buildFlags;
206
        return $target;
207
    }
208
209
    /**
210
     * @return FileLocation
211
     */
212
    public function getFileLocation(): FileLocation
213
    {
214
        return $this->fileLocation;
215
    }
216
217
    /**
218
     * @return string
219
     */
220
    public function getFileName(): string
221
    {
222
        return $this->fileName;
223
    }
224
225
    /**
226
     * @return string
227
     */
228
    public function getUrl(): string
229
    {
230
        return $this->fileLocation->getBaseUrl() . $this->fileName;
231
    }
232
233
    /**
234
     * @return bool
235
     */
236
    public function shallFail(): bool
237
    {
238
        return $this->fail;
239
    }
240
241
    /**
242
     * @return string|null
243
     */
244
    public function getExpectedContentType(): ?string
245
    {
246
        return $this->expectedContentType;
247
    }
248
249
    /**
250
     * @return string|null
251
     */
252
    public function getUnexpectedContentType(): ?string
253
    {
254
        return $this->unexpectedContentType;
255
    }
256
257
    /**
258
     * @return string|null
259
     */
260
    public function getExpectedContent(): ?string
261
    {
262
        return $this->expectedContent;
263
    }
264
265
    /**
266
     * @return string|null
267
     */
268
    public function getUnexpectedContent(): ?string
269
    {
270
        return $this->unexpectedContent;
271
    }
272
}
273