InteractsWithContentTypes   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 168
Duplicated Lines 0 %

Test Coverage

Coverage 3.77%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 43
c 1
b 0
f 0
dl 0
loc 168
ccs 2
cts 53
cp 0.0377
rs 9.68
wmc 34

10 Methods

Rating   Name   Duplication   Size   Complexity  
B accepts() 0 23 8
A acceptsAnyContentType() 0 6 4
A format() 0 9 3
A acceptsHtml() 0 3 1
A wantsJson() 0 5 2
A acceptsJson() 0 3 1
A isJson() 0 3 1
B prefers() 0 20 7
A expectsJson() 0 3 4
A matchesType() 0 12 3
1
<?php
2
3
namespace Nip\Http\Traits;
4
5
use Nip\Utility\Str;
6
7
/**
8
 * Trait InteractsWithContentTypes
9
 * @package Nip\Http\Traits
10
 */
11
trait InteractsWithContentTypes
12
{
13
14
    /**
15
     * Determine if the given content types match.
16
     *
17
     * @param string $actual
18
     * @param string $type
19
     * @return bool
20
     */
21
    public static function matchesType($actual, $type)
22
    {
23
        if ($actual === $type) {
24
            return true;
25
        }
26
27
        $split = explode('/', $actual);
28
29
        return isset($split[1])
30
            && preg_match(
31
                '#' . preg_quote($split[0], '#') . '/.+\+' . preg_quote($split[1], '#') . '#',
32
                $type
33
            );
34
    }
35
36
    /**
37
     * Determine if the request is sending JSON.
38
     *
39
     * @return bool
40
     */
41 1
    public function isJson()
42
    {
43 1
        return Str::contains($this->header('CONTENT_TYPE'), ['/json', '+json']);
0 ignored issues
show
Bug introduced by
It seems like header() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

43
        return Str::contains($this->/** @scrutinizer ignore-call */ header('CONTENT_TYPE'), ['/json', '+json']);
Loading history...
44
    }
45
46
    /**
47
     * Determine if the current request probably expects a JSON response.
48
     *
49
     * @return bool
50
     */
51
    public function expectsJson()
52
    {
53
        return ($this->ajax() && !$this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
0 ignored issues
show
Bug introduced by
It seems like ajax() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
        return ($this->/** @scrutinizer ignore-call */ ajax() && !$this->pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
Loading history...
Bug introduced by
It seems like pjax() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
        return ($this->ajax() && !$this->/** @scrutinizer ignore-call */ pjax() && $this->acceptsAnyContentType()) || $this->wantsJson();
Loading history...
54
    }
55
56
    /**
57
     * Determine if the current request is asking for JSON.
58
     *
59
     * @return bool
60
     */
61
    public function wantsJson()
62
    {
63
        $acceptable = $this->getAcceptableContentTypes();
0 ignored issues
show
Bug introduced by
It seems like getAcceptableContentTypes() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
        /** @scrutinizer ignore-call */ 
64
        $acceptable = $this->getAcceptableContentTypes();
Loading history...
64
65
        return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']);
66
    }
67
68
    /**
69
     * Determines whether the current requests accepts a given content type.
70
     *
71
     * @param string|array $contentTypes
72
     * @return bool
73
     */
74
    public function accepts($contentTypes)
75
    {
76
        $accepts = $this->getAcceptableContentTypes();
77
78
        if (count($accepts) === 0) {
79
            return true;
80
        }
81
82
        $types = (array)$contentTypes;
83
84
        foreach ($accepts as $accept) {
85
            if ($accept === '*/*' || $accept === '*') {
86
                return true;
87
            }
88
89
            foreach ($types as $type) {
90
                if ($this->matchesType($accept, $type) || $accept === strtok($type, '/') . '/*') {
91
                    return true;
92
                }
93
            }
94
        }
95
96
        return false;
97
    }
98
99
    /**
100
     * Return the most suitable content type from the given array based on content negotiation.
101
     *
102
     * @param string|array $contentTypes
103
     * @return string|null
104
     */
105
    public function prefers($contentTypes)
106
    {
107
        $accepts = $this->getAcceptableContentTypes();
108
109
        $contentTypes = (array)$contentTypes;
110
111
        foreach ($accepts as $accept) {
112
            if (in_array($accept, ['*/*', '*'])) {
113
                return $contentTypes[0];
114
            }
115
116
            foreach ($contentTypes as $contentType) {
117
                $type = $contentType;
118
119
                if (!is_null($mimeType = $this->getMimeType($contentType))) {
0 ignored issues
show
Bug introduced by
It seems like getMimeType() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
                if (!is_null($mimeType = $this->/** @scrutinizer ignore-call */ getMimeType($contentType))) {
Loading history...
120
                    $type = $mimeType;
121
                }
122
123
                if ($this->matchesType($type, $accept) || $accept === strtok($type, '/') . '/*') {
124
                    return $contentType;
125
                }
126
            }
127
        }
128
    }
129
130
    /**
131
     * Determine if the current request accepts any content type.
132
     *
133
     * @return bool
134
     */
135
    public function acceptsAnyContentType()
136
    {
137
        $acceptable = $this->getAcceptableContentTypes();
138
139
        return count($acceptable) === 0 || (
140
                isset($acceptable[0]) && ($acceptable[0] === '*/*' || $acceptable[0] === '*')
141
            );
142
    }
143
144
    /**
145
     * Determines whether a request accepts JSON.
146
     *
147
     * @return bool
148
     */
149
    public function acceptsJson()
150
    {
151
        return $this->accepts('application/json');
152
    }
153
154
    /**
155
     * Determines whether a request accepts HTML.
156
     *
157
     * @return bool
158
     */
159
    public function acceptsHtml()
160
    {
161
        return $this->accepts('text/html');
162
    }
163
164
    /**
165
     * Get the data format expected in the response.
166
     *
167
     * @param string $default
168
     * @return string
169
     */
170
    public function format($default = 'html')
171
    {
172
        foreach ($this->getAcceptableContentTypes() as $type) {
173
            if ($format = $this->getFormat($type)) {
0 ignored issues
show
Bug introduced by
It seems like getFormat() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

173
            if ($format = $this->/** @scrutinizer ignore-call */ getFormat($type)) {
Loading history...
174
                return $format;
175
            }
176
        }
177
178
        return $default;
179
    }
180
}
181