Passed
Branch php72 (a3eac9)
by Joni
03:37
created

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