ContentNegotiation::negotiateContentType()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Jasny\Controller\Traits;
5
6
use Negotiation\AbstractNegotiator;
7
use Negotiation\Negotiator;
8
use Negotiation\LanguageNegotiator;
9
use Negotiation\EncodingNegotiator;
10
use Negotiation\CharsetNegotiator;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
14
/**
15
 * Controller methods to negotiate content
16
 */
17
trait ContentNegotiation
18
{
19
    abstract protected function getRequest(): ServerRequestInterface;
20
    abstract protected function getResponse(): ResponseInterface;
21
22
    abstract protected function header(string $header, string|int|\Stringable $value, bool $add = false): static;
23
24
    /**
25
     * Pick the best content type
26
     *
27
     * @param string[] $priorities
28
     * @return string
29
     */
30
    protected function negotiateContentType(array $priorities): string
31
    {
32
        $contentType = $this->negotiate(new Negotiator(), 'Accept', $priorities);
33
34
        if ($contentType !== '') {
35
            $this->header('Content-Type', $contentType);
36
        }
37
38
        return $contentType;
39
    }
40
41
    /**
42
     * Pick the best language and set the `Content-Language` header
43
     *
44
     * @param string[] $priorities
45
     * @return string
46
     */
47
    protected function negotiateLanguage(array $priorities): string
48
    {
49
        $language = $this->negotiate(new LanguageNegotiator(), 'Accept-Language', $priorities);
50
51
        if ($language !== '') {
52
            $this->header('Content-Language', $language);
53
        }
54
55
        return $language;
56
    }
57
58
    /**
59
     * Pick the best encoding and set `Content-Encoding` header
60
     *
61
     * @param string[] $priorities
62
     * @return string
63
     */
64
    protected function negotiateEncoding(array $priorities): string
65
    {
66
        $encoding = $this->negotiate(new EncodingNegotiator(), 'Accept-Encoding', $priorities);
67
68
        if ($encoding !== '') {
69
            $this->header('Content-Encoding', $encoding);
70
        }
71
72
        return $encoding;
73
    }
74
75
    /**
76
     * Pick the best charset.
77
     * This method will modify the `Content-Type` header if it's set.
78
     *
79
     * @param string[] $priorities
80
     * @return string
81
     */
82
    protected function negotiateCharset(array $priorities): string
83
    {
84
        $charset = $this->negotiate(new CharsetNegotiator(), 'Accept-Charset', $priorities);
85
86
        $contentType = $this->getResponse()->getHeaderLine('Content-Type');
87
        if ($contentType !== '') {
88
            $contentType = preg_replace('/;\s*charset\s*=[^;]+/', '', $contentType)
89
                . "; charset=$charset";
90
            $this->header('Content-Type', $contentType);
91
        }
92
93
        return $charset;
94
    }
95
96
    /**
97
     * Generalize negotiation.
98
     */
99
    private function negotiate(AbstractNegotiator $negotiator, string $header, array $priorities): string
100
    {
101
        $value = $this->getRequest()->getHeaderLine($header);
102
        $chosen = $negotiator->getBest($value, $priorities);
103
104
        return $chosen !== null ? $chosen->getType() : '';
105
    }
106
}
107