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