Completed
Push — master ( 0f92f9...600ea9 )
by Tobias
04:40
created

ContentTypePlugin::isXml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Http\Client\Common\Plugin;
4
5
use Http\Client\Common\Plugin;
6
use Psr\Http\Message\RequestInterface;
7
use Psr\Http\Message\StreamInterface;
8
use Symfony\Component\OptionsResolver\OptionsResolver;
9
10
/**
11
 * Allow to set the correct content type header on the request automatically only if it is not set.
12
 *
13
 * @author Karim Pinchon <[email protected]>
14
 */
15
final class ContentTypePlugin implements Plugin
16
{
17
    /**
18
     * Allow to disable the content type detection when stream is too large (as it can consume a lot of resource).
19
     *
20
     * @var bool
21
     *
22
     * true     skip the content type detection
23
     * false    detect the content type (default value)
24
     */
25
    protected $skipDetection;
26
27
    /**
28
     * Determine the size stream limit for which the detection as to be skipped (default to 16Mb).
29
     *
30
     * @var int
31
     */
32
    protected $sizeLimit;
33
34
    /**
35
     * @param array $config {
36
     *
37
     *     @var bool $skip_detection True skip detection if stream size is bigger than $size_limit.
38
     *     @var int $size_limit size stream limit for which the detection as to be skipped.
39
     * }
40
     */
41 10
    public function __construct(array $config = [])
42
    {
43 10
        $resolver = new OptionsResolver();
44 10
        $resolver->setDefaults([
45 10
            'skip_detection' => false,
46 10
            'size_limit' => 16000000,
47 10
        ]);
48 10
        $resolver->setAllowedTypes('skip_detection', 'bool');
49 10
        $resolver->setAllowedTypes('size_limit', 'int');
50
51 10
        $options = $resolver->resolve($config);
52
53 10
        $this->skipDetection = $options['skip_detection'];
54 10
        $this->sizeLimit = $options['size_limit'];
55 10
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 8
    public function handleRequest(RequestInterface $request, callable $next, callable $first)
61
    {
62 8
        if (!$request->hasHeader('Content-Type')) {
63 7
            $stream = $request->getBody();
64 7
            $streamSize = $stream->getSize();
65
66 7
            if (!$stream->isSeekable()) {
67
                return $next($request);
68
            }
69
70 7
            if (0 === $streamSize) {
71 1
                return $next($request);
72
            }
73
74 6
            if ($this->skipDetection && (null === $streamSize || $streamSize >= $this->sizeLimit)) {
75 1
                return $next($request);
76
            }
77
78 5
            if ($this->isJson($stream)) {
79 1
                $request = $request->withHeader('Content-Type', 'application/json');
80
81 1
                return $next($request);
82
            }
83
84 4
            if ($this->isXml($stream)) {
85 3
                $request = $request->withHeader('Content-Type', 'application/xml');
86
87 3
                return $next($request);
88
            }
89 1
        }
90
91 2
        return $next($request);
92
    }
93
94
    /**
95
     * @param $stream StreamInterface
96
     *
97
     * @return bool
98
     */
99 5
    private function isJson($stream)
100
    {
101 5
        $stream->rewind();
102
103 5
        json_decode($stream->getContents());
104
105 5
        return json_last_error() == JSON_ERROR_NONE;
106
    }
107
108
    /**
109
     * @param $stream StreamInterface
110
     *
111
     * @return \SimpleXMLElement|false
112
     */
113 4
    private function isXml($stream)
114
    {
115 4
        $stream->rewind();
116
117 4
        $previousValue = libxml_use_internal_errors(true);
118 4
        $isXml = simplexml_load_string($stream->getContents());
119 4
        libxml_use_internal_errors($previousValue);
120
121 4
        return $isXml;
122
    }
123
}
124