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\Request;
12
13use FreeDSx\Asn1\Asn1;
14use FreeDSx\Asn1\Type\AbstractType;
15use FreeDSx\Asn1\Type\OctetStringType;
16use FreeDSx\Asn1\Type\SequenceType;
17use FreeDSx\Ldap\Entry\Dn;
18use FreeDSx\Ldap\Exception\ProtocolException;
19use FreeDSx\Ldap\Search\Filter\EqualityFilter;
20
21/**
22 * An attribute-value comparison request. RFC 4511, 4.10.
23 *
24 * CompareRequest ::= [APPLICATION 14] SEQUENCE {
25 *     entry           LDAPDN,
26 *     ava             AttributeValueAssertion }
27 *
28 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
29 */
30class CompareRequest implements RequestInterface, DnRequestInterface
31{
32    protected const APP_TAG = 14;
33
34    /**
35     * @var Dn
36     */
37    protected $dn;
38
39    /**
40     * @var EqualityFilter
41     */
42    protected $filter;
43
44    /**
45     * @param string|Dn $dn
46     * @param EqualityFilter $filter
47     */
48    public function __construct($dn, EqualityFilter $filter)
49    {
50        $this->setDn($dn);
51        $this->filter = $filter;
52    }
53
54    /**
55     * @return Dn
56     */
57    public function getDn(): Dn
58    {
59        return $this->dn;
60    }
61
62    /**
63     * @param string|Dn $dn
64     * @return $this
65     */
66    public function setDn($dn)
67    {
68        $this->dn = $dn instanceof Dn ? $dn : new Dn($dn);
69
70        return $this;
71    }
72
73    /**
74     * @return EqualityFilter
75     */
76    public function getFilter(): EqualityFilter
77    {
78        return $this->filter;
79    }
80
81    /**
82     * @param EqualityFilter $filter
83     * @return $this
84     */
85    public function setFilter(EqualityFilter $filter)
86    {
87        $this->filter = $filter;
88
89        return $this;
90    }
91
92    /**
93     * {@inheritdoc}
94     */
95    public static function fromAsn1(AbstractType $type)
96    {
97        if (!($type instanceof SequenceType && count($type->getChildren()) === 2)) {
98            throw new ProtocolException('The compare request is malformed');
99        }
100        $dn = $type->getChild(0);
101        $ava = $type->getChild(1);
102
103        if (!$dn instanceof OctetStringType || $ava === null) {
104            throw new ProtocolException('The compare request is malformed.');
105        }
106
107        return new self($dn->getValue(), EqualityFilter::fromAsn1($ava));
108    }
109
110    /**
111     * {@inheritdoc}
112     */
113    public function toAsn1(): AbstractType
114    {
115        return Asn1::application(self::APP_TAG, Asn1::sequence(
116            Asn1::octetString($this->dn->toString()),
117            Asn1::universal(AbstractType::TAG_TYPE_SEQUENCE, $this->filter->toAsn1())
118        ));
119    }
120}
121