Repository navigation
Expand file tree
/
Copy pathEncoderDetector.php
More file actions
123 lines (103 loc) · 3.75 KB
/
Copy pathEncoderDetector.php
File metadata and controls
123 lines (103 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<?php
declare(strict_types=1);
namespace Soap\Encoding\Encoder\SimpleType;
use Soap\Encoding\Encoder\Context;
use Soap\Encoding\Encoder\ElementEncoder;
use Soap\Encoding\Encoder\Feature;
use Soap\Encoding\Encoder\OptionalElementEncoder;
use Soap\Encoding\Encoder\XmlEncoder;
use Soap\Encoding\Encoder\XsiTypeEncoder;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Node\ElementList;
use Soap\Engine\Metadata\Model\XsdType;
use function Psl\Iter\any;
final class EncoderDetector
{
public static function default(): self
{
/** @var self $self */
static $self = new self();
return $self;
}
/**
* @return XmlEncoder<mixed, mixed, string|null, ElementList|Element|string|null>
*/
public function __invoke(Context $context): XmlEncoder
{
return $this->enhanceEncoder(
$context,
$this->detectSimpleTypeEncoder($context)
);
}
/**
* @param XmlEncoder<mixed, mixed, string, string> $encoder
* @return XmlEncoder<mixed, mixed, string|null, ElementList|Element|string|null>
*/
private function enhanceEncoder(Context $context, XmlEncoder $encoder): XmlEncoder
{
$type = $context->type;
$meta = $type->getMeta();
if (!$encoder instanceof Feature\ListAware && $this->detectIsListType($type)) {
$encoder = new SimpleListEncoder($encoder);
}
if ($meta->isAttribute()->unwrapOr(false)) {
return new AttributeValueEncoder($encoder);
}
if ($meta->isElement()->unwrapOr(false)) {
if (!$encoder instanceof Feature\ElementAware) {
$encoder = new ElementEncoder($encoder);
}
if (!$encoder instanceof Feature\DisregardXsiInformation && !$context->skipXsiTypeDetection) {
$encoder = new XsiTypeEncoder($encoder);
}
if ($meta->isNullable()->unwrapOr(false) && !$encoder instanceof Feature\OptionalAware) {
$encoder = new OptionalElementEncoder($encoder);
}
}
return $encoder;
}
/**
* @return XmlEncoder<mixed, mixed, string, string>
*/
private function detectSimpleTypeEncoder(Context $context): XmlEncoder
{
$type = $context->type;
$meta = $type->getMeta();
// Try to find a direct match:
if ($context->registry->hasRegisteredSimpleTypeForXsdType($type)) {
return $context->registry->findSimpleEncoderByXsdType($type);
}
// Try to find a match for the extended simple type:
// Or fallback to the default scalar encoder.
return $meta->extends()
->filter(static fn ($extend): bool => $extend['isSimple'] ?? false)
->map(static fn ($extends) : XmlEncoder => $context->registry->findSimpleEncoderByNamespaceName(
$extends['namespace'],
$extends['type'],
))
->unwrapOr(ScalarTypeEncoder::default());
}
private function detectIsListType(XsdType $type): bool
{
$meta = $type->getMeta();
// Repeating elements will be decorated inside the regular EncoderDetector.
// There is no need to add a list encoder for repeating elements.
if ($meta->isRepeatingElement()->unwrapOr(false)) {
return false;
}
if ($meta->isList()->unwrapOr(false)) {
return true;
}
$unions = $meta->unions();
$unionsContainsList = $unions
->map(static fn (array $unionList): bool => any(
$unionList,
static fn (array $union): bool => $union['isList']
))
->unwrapOr(false);
if ($unionsContainsList) {
return true;
}
return false;
}
}