1<?php
2
3/**
4 * This file is part of the FreeDSx LDAP package.
5 *
6 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace FreeDSx\Ldap\Operation\Response;
13
14use FreeDSx\Asn1\Asn1;
15use FreeDSx\Asn1\Type\AbstractType;
16use FreeDSx\Asn1\Type\SequenceType;
17use FreeDSx\Ldap\Exception\ProtocolException;
18
19/**
20 * RFC 4511, 4.13.
21 *
22 * IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
23 *     responseName     [0] LDAPOID OPTIONAL,
24 *     responseValue    [1] OCTET STRING OPTIONAL }
25 *
26 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
27 */
28class IntermediateResponse implements ResponseInterface
29{
30    protected const TAG_NUMBER = 25;
31
32    /**
33     * @var null|string
34     */
35    protected $responseName;
36
37    /**
38     * @var null|string
39     */
40    protected $responseValue;
41
42    /**
43     * @param null|string $responseName
44     * @param null|string $responseValue
45     */
46    public function __construct(?string $responseName, ?string $responseValue)
47    {
48        $this->responseName = $responseName;
49        $this->responseValue = $responseValue;
50    }
51
52    /**
53     * @return null|string
54     */
55    public function getName(): ?string
56    {
57        return $this->responseName;
58    }
59
60    /**
61     * @return null|string
62     */
63    public function getValue(): ?string
64    {
65        return $this->responseValue;
66    }
67
68    /**
69     * @param AbstractType $type
70     * @return self
71     * @throws ProtocolException
72     */
73    public static function fromAsn1(AbstractType $type)
74    {
75        if (!$type instanceof SequenceType) {
76            throw new ProtocolException('The intermediate response is malformed');
77        }
78
79        $name = null;
80        $value = null;
81        foreach ($type->getChildren() as $child) {
82            if ($child->getTagNumber() === 0 && $child->getTagClass() === AbstractType::TAG_CLASS_CONTEXT_SPECIFIC) {
83                $name = $child->getValue();
84            }
85            if ($child->getTagNumber() === 1 && $child->getTagClass() === AbstractType::TAG_CLASS_CONTEXT_SPECIFIC) {
86                $value = $child->getValue();
87            }
88        }
89
90        return new self($name, $value);
91    }
92
93    /**
94     * {@inheritdoc}
95     */
96    public function toAsn1(): AbstractType
97    {
98        $response = Asn1::sequence();
99
100        if ($this->responseName !== null) {
101            $response->addChild(Asn1::context(0, Asn1::octetString($this->responseName)));
102        }
103        if ($this->responseValue !== null) {
104            $response->addChild(Asn1::context(1, Asn1::octetString($this->responseValue)));
105        }
106
107        return Asn1::application(self::TAG_NUMBER, $response);
108    }
109}
110