SimpleConverterMatcher::match()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 14
c 2
b 0
f 0
nc 7
nop 1
dl 0
loc 29
ccs 0
cts 14
cp 0
crap 56
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace roxblnfk\SmartStream\Matching;
6
7
use Generator;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Message\RequestInterface;
10
use roxblnfk\SmartStream\ConverterInterface;
11
use roxblnfk\SmartStream\ConverterMatcherInterface;
12
use roxblnfk\SmartStream\Data\DataBucket;
13
use roxblnfk\SmartStream\Exception\ConverterNotFoundException;
14
use Yiisoft\Http\Header;
15
16
final class SimpleConverterMatcher implements ConverterMatcherInterface
17
{
18
    private SimpleMatcherConfig $matcherConfig;
19
    private ContainerInterface $container;
20
    private ?RequestInterface $request = null;
21
22 1
    public function __construct(ContainerInterface $container, SimpleMatcherConfig $matcherConfig)
23
    {
24 1
        $this->container = $container;
25 1
        $this->matcherConfig = $matcherConfig;
26 1
    }
27
28
    public function match(DataBucket $bucket): ?MatchingResult
29
    {
30
        if (!$bucket->isConvertable()) {
31
            return null;
32
        }
33
34
        # find by format from bucket
35
        # find by bucket class name
36
        $format = $this->getBucketFormat($bucket) ?? $this->getBucketClassFormat($bucket);
37
        if ($format === null) {
38
            return null;
39
        }
40
41
        # multiple formats
42
        if (is_array($format)) {
43
            # if content-type specified in the bucket
44
            if (count($format) > 1 && $bucket->hasHeader(Header::CONTENT_TYPE)) {
45
                $format = $this->selectFormatByPreferredContentType($format, $bucket->getHeaderLine(Header::CONTENT_TYPE));
0 ignored issues
show
Bug introduced by
It seems like $bucket->getHeaderLine(Y...p\Header::CONTENT_TYPE) can also be of type null; however, parameter $contentType of roxblnfk\SmartStream\Mat...yPreferredContentType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

45
                $format = $this->selectFormatByPreferredContentType($format, /** @scrutinizer ignore-type */ $bucket->getHeaderLine(Header::CONTENT_TYPE));
Loading history...
46
            }
47
            if (count($format) > 1) {
48
                # find format by headers
49
                $format = $this->compareWithAcceptTypes($format) ?? current($format);
50
            } else {
51
                $format = current($format);
52
            }
53
        }
54
55
        $converter = $this->container->get($this->matcherConfig->getConverter($format));
56
        return new MatchingResult($format, $converter, $this->matcherConfig->getMimeType($format));
57
    }
58 1
    public function withRequest(?RequestInterface $request): ConverterMatcherInterface
59
    {
60 1
        $new = clone $this;
61 1
        $new->request = $request;
62 1
        return $new;
63
    }
64
65
    private function getBucketFormat(DataBucket $bucket): ?string
66
    {
67
        if ($bucket->hasFormat()) {
68
            $format = $bucket->getFormat();
69
            if (!$this->matcherConfig->hasFormat($format)) {
70
                throw new ConverterNotFoundException($format);
71
            }
72
            return $format;
73
        }
74
        return null;
75
    }
76
    private function getBucketClassFormat(DataBucket $bucket): ?array
77
    {
78
        $className = static function (DataBucket $bucket): Generator {
79
            yield get_class($bucket);
80
            yield from class_parents($bucket);
81
        };
82
        $result = [];
83
        foreach ($className($bucket) as $bucketClass) {
84
            if ($this->matcherConfig->hasBucketFormat($bucketClass)) {
85
                $result = array_merge($result, $this->matcherConfig->getBucketFormats($bucketClass));
86
            }
87
        }
88
        return count($result) > 0 ? array_unique($result) : null;
89
    }
90
    private function selectFormatByPreferredContentType(array $formats, string $contentType): array
91
    {
92
        foreach ($formats as $format) {
93
            if ($this->matcherConfig->getMimeType($format) === $contentType) {
94
                # todo
95
            }
96
        }
97
        return $formats;
98
    }
99
    /**
100
     * @param string[] $format
101
     * @return null|string
102
     */
103
    private function compareWithAcceptTypes(array $format): ?string
104
    {
105
        return current($format);
106
        # TODO
107
        // $header = $this->request->getHeaderLine(Header::ACCEPT);
108
        // return null;
109
    }
110
}
111