Passed
Push — master ( d10e8c...c6bdb0 )
by Joni
03:28
created

DirectoryString::toASN1()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\X501\ASN1\AttributeValue\Feature;
6
7
use Sop\ASN1\Element;
8
use Sop\ASN1\Type\Primitive\BMPString;
9
use Sop\ASN1\Type\Primitive\PrintableString;
10
use Sop\ASN1\Type\Primitive\T61String;
11
use Sop\ASN1\Type\Primitive\UniversalString;
12
use Sop\ASN1\Type\Primitive\UTF8String;
13
use Sop\ASN1\Type\UnspecifiedType;
14
use Sop\X501\ASN1\AttributeValue\AttributeValue;
15
use Sop\X501\DN\DNParser;
16
use Sop\X501\MatchingRule\CaseIgnoreMatch;
17
use Sop\X501\MatchingRule\MatchingRule;
18
use Sop\X501\StringPrep\TranscodeStep;
19
20
/**
21
 * Base class for attribute values having *(Unbounded)DirectoryString* as a syntax.
22
 *
23
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2012/SelectedAttributeTypes.html#SelectedAttributeTypes.UnboundedDirectoryString
24
 */
25
abstract class DirectoryString extends AttributeValue
26
{
27
    /**
28
     * Teletex string syntax.
29
     *
30
     * @var int
31
     */
32
    const TELETEX = Element::TYPE_T61_STRING;
33
34
    /**
35
     * Printable string syntax.
36
     *
37
     * @var int
38
     */
39
    const PRINTABLE = Element::TYPE_PRINTABLE_STRING;
40
41
    /**
42
     * BMP string syntax.
43
     *
44
     * @var int
45
     */
46
    const BMP = Element::TYPE_BMP_STRING;
47
48
    /**
49
     * Universal string syntax.
50
     *
51
     * @var int
52
     */
53
    const UNIVERSAL = Element::TYPE_UNIVERSAL_STRING;
54
55
    /**
56
     * UTF-8 string syntax.
57
     *
58
     * @var int
59
     */
60
    const UTF8 = Element::TYPE_UTF8_STRING;
61
62
    /**
63
     * Mapping from syntax enumeration to ASN.1 class name.
64
     *
65
     * @internal
66
     *
67
     * @var array
68
     */
69
    const MAP_TAG_TO_CLASS = [
70
        self::TELETEX => T61String::class,
71
        self::PRINTABLE => PrintableString::class,
72
        self::UNIVERSAL => UniversalString::class,
73
        self::UTF8 => UTF8String::class,
74
        self::BMP => BMPString::class,
75
    ];
76
77
    /**
78
     * ASN.1 type tag for the chosen syntax.
79
     *
80
     * @var int
81
     */
82
    protected $_stringTag;
83
84
    /**
85
     * String value.
86
     *
87
     * @var string
88
     */
89
    protected $_string;
90
91
    /**
92
     * Constructor.
93
     *
94
     * @param string $value      String value
95
     * @param int    $string_tag Syntax choice
96
     */
97 66
    public function __construct(string $value, int $string_tag)
98
    {
99 66
        $this->_string = $value;
100 66
        $this->_stringTag = $string_tag;
101 66
    }
102
103
    /**
104
     * {@inheritdoc}
105
     *
106
     * @return self
107
     */
108 48
    public static function fromASN1(UnspecifiedType $el): AttributeValue
109
    {
110 48
        $tag = $el->tag();
111 48
        self::_tagToASN1Class($tag);
112 47
        return new static($el->asString()->string(), $tag);
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 18
    public function toASN1(): Element
119
    {
120 18
        $cls = self::_tagToASN1Class($this->_stringTag);
121 17
        return new $cls($this->_string);
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 18
    public function stringValue(): string
128
    {
129 18
        return $this->_string;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135 17
    public function equalityMatchingRule(): MatchingRule
136
    {
137 17
        return new CaseIgnoreMatch($this->_stringTag);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 17
    public function rfc2253String(): string
144
    {
145
        // TeletexString is encoded as binary
146 17
        if (self::TELETEX === $this->_stringTag) {
147 1
            return $this->_transcodedString();
148
        }
149 16
        return DNParser::escapeString($this->_transcodedString());
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155 17
    protected function _transcodedString(): string
156
    {
157 17
        $step = new TranscodeStep($this->_stringTag);
158 17
        return $step->apply($this->_string);
159
    }
160
161
    /**
162
     * Get ASN.1 class name for given DirectoryString type tag.
163
     *
164
     * @param int $tag
165
     *
166
     * @throws \UnexpectedValueException
167
     *
168
     * @return string
169
     */
170 64
    private static function _tagToASN1Class(int $tag): string
171
    {
172 64
        if (!array_key_exists($tag, self::MAP_TAG_TO_CLASS)) {
173 2
            throw new \UnexpectedValueException(
174 2
                'Type ' . Element::tagToName($tag) .
175 2
                ' is not valid DirectoryString.');
176
        }
177 62
        return self::MAP_TAG_TO_CLASS[$tag];
178
    }
179
}
180