AttributeValue   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 8
eloc 27
dl 0
loc 155
ccs 18
cts 18
cp 1
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A toAttributeTypeAndValue() 0 3 1
A toAttribute() 0 3 1
A fromASN1ByOID() 0 7 2
A fromASN1() 0 4 1
A fromSelf() 0 3 1
A oid() 0 3 1
A __toString() 0 3 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\X501\ASN1\AttributeValue;
6
7
use Sop\ASN1\Element;
8
use Sop\ASN1\Type\UnspecifiedType;
9
use Sop\X501\ASN1\Attribute;
10
use Sop\X501\ASN1\AttributeType;
11
use Sop\X501\ASN1\AttributeTypeAndValue;
12
use Sop\X501\MatchingRule\MatchingRule;
13
14
/**
15
 * Base class for attribute values.
16
 *
17
 * @see https://www.itu.int/ITU-T/formal-language/itu-t/x/x501/2012/InformationFramework.html#InformationFramework.AttributeValue
18
 */
19
abstract class AttributeValue
20
{
21
    /**
22
     * Mapping from attribute type OID to attribute value class name.
23
     *
24
     * @internal
25
     *
26
     * @var array
27
     */
28
    const MAP_OID_TO_CLASS = [
29
        AttributeType::OID_COMMON_NAME => CommonNameValue::class,
30
        AttributeType::OID_SURNAME => SurnameValue::class,
31
        AttributeType::OID_SERIAL_NUMBER => SerialNumberValue::class,
32
        AttributeType::OID_COUNTRY_NAME => CountryNameValue::class,
33
        AttributeType::OID_LOCALITY_NAME => LocalityNameValue::class,
34
        AttributeType::OID_STATE_OR_PROVINCE_NAME => StateOrProvinceNameValue::class,
35
        AttributeType::OID_ORGANIZATION_NAME => OrganizationNameValue::class,
36
        AttributeType::OID_ORGANIZATIONAL_UNIT_NAME => OrganizationalUnitNameValue::class,
37
        AttributeType::OID_TITLE => TitleValue::class,
38
        AttributeType::OID_DESCRIPTION => DescriptionValue::class,
39
        AttributeType::OID_NAME => NameValue::class,
40
        AttributeType::OID_GIVEN_NAME => GivenNameValue::class,
41
        AttributeType::OID_PSEUDONYM => PseudonymValue::class,
42
    ];
43
44
    /**
45
     * OID of the attribute type.
46
     *
47
     * @var string
48
     */
49
    protected $_oid;
50
51
    /**
52
     * Get attribute value as an UTF-8 encoded string.
53
     *
54
     * @return string
55
     */
56 1
    public function __toString()
57
    {
58 1
        return $this->_transcodedString();
59
    }
60
61
    /**
62
     * Generate ASN.1 element.
63
     *
64
     * @return Element
65
     */
66
    abstract public function toASN1(): Element;
67
68
    /**
69
     * Get attribute value as a string.
70
     *
71
     * @return string
72
     */
73
    abstract public function stringValue(): string;
74
75
    /**
76
     * Get matching rule for equality comparison.
77
     *
78
     * @return MatchingRule
79
     */
80
    abstract public function equalityMatchingRule(): MatchingRule;
81
82
    /**
83
     * Get attribute value as a string conforming to RFC 2253.
84
     *
85
     * @see https://tools.ietf.org/html/rfc2253#section-2.4
86
     *
87
     * @return string
88
     */
89
    abstract public function rfc2253String(): string;
90
91
    /**
92
     * Initialize from ASN.1.
93
     *
94
     * @param UnspecifiedType $el
95
     *
96
     * @return self
97
     */
98 1
    public static function fromASN1(UnspecifiedType $el): AttributeValue
99
    {
100 1
        throw new \BadMethodCallException(
101 1
            'ASN.1 parsing must be implemented in a concrete class.');
102
    }
103
104
    /**
105
     * Initialize from ASN.1 with given OID hint.
106
     *
107
     * @param string          $oid Attribute's OID
108
     * @param UnspecifiedType $el
109
     *
110
     * @return self
111
     */
112 57
    public static function fromASN1ByOID(string $oid, UnspecifiedType $el): self
113
    {
114 57
        if (!array_key_exists($oid, self::MAP_OID_TO_CLASS)) {
115 6
            return new UnknownAttributeValue($oid, $el->asElement());
116
        }
117 52
        $cls = self::MAP_OID_TO_CLASS[$oid];
118 52
        return $cls::fromASN1($el);
119
    }
120
121
    /**
122
     * Initialize from another AttributeValue.
123
     *
124
     * This method is generally used to cast UnknownAttributeValue to
125
     * specific object when class is declared outside this package.
126
     *
127
     * @param self $obj Instance of AttributeValue
128
     *
129
     * @return self
130
     */
131 3
    public static function fromSelf(self $obj): self
132
    {
133 3
        return static::fromASN1($obj->toASN1()->asUnspecified());
134
    }
135
136
    /**
137
     * Get attribute type's OID.
138
     *
139
     * @return string
140
     */
141 18
    public function oid(): string
142
    {
143 18
        return $this->_oid;
144
    }
145
146
    /**
147
     * Get Attribute object with this as a single value.
148
     *
149
     * @return Attribute
150
     */
151 5
    public function toAttribute(): Attribute
152
    {
153 5
        return Attribute::fromAttributeValues($this);
154
    }
155
156
    /**
157
     * Get AttributeTypeAndValue object with this as a value.
158
     *
159
     * @return AttributeTypeAndValue
160
     */
161 1
    public function toAttributeTypeAndValue(): AttributeTypeAndValue
162
    {
163 1
        return AttributeTypeAndValue::fromAttributeValue($this);
164
    }
165
166
    /**
167
     * Get attribute value as an UTF-8 string conforming to RFC 4518.
168
     *
169
     * @see https://tools.ietf.org/html/rfc4518#section-2.1
170
     *
171
     * @return string
172
     */
173
    abstract protected function _transcodedString(): string;
174
}
175