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\Control\Sorting;
13
14use FreeDSx\Asn1\Asn1;
15use FreeDSx\Asn1\Exception\EncoderException;
16use FreeDSx\Asn1\Exception\PartialPduException;
17use FreeDSx\Asn1\Type\AbstractType;
18use FreeDSx\Asn1\Type\EnumeratedType;
19use FreeDSx\Asn1\Type\SequenceType;
20use FreeDSx\Ldap\Control\Control;
21use FreeDSx\Ldap\Exception\ProtocolException;
22
23/**
24 * A Server Side Sorting response control value. RFC 2891.
25 *
26 * SortResult ::= SEQUENCE {
27 *     sortResult  ENUMERATED {
28 *         success                   (0), -- results are sorted
29 *         operationsError           (1), -- server internal failure
30 *         timeLimitExceeded         (3), -- timelimit reached before
31 *         -- sorting was completed
32 *         strongAuthRequired        (8), -- refused to return sorted
33 *                                        -- results via insecure
34 *                                        -- protocol
35 *         adminLimitExceeded       (11), -- too many matching entries
36 *                                        -- for the server to sort
37 *         noSuchAttribute          (16), -- unrecognized attribute
38 *                                        -- type in sort key
39 *         inappropriateMatching    (18), -- unrecognized or
40 *                                        -- inappropriate matching
41 *                                        -- rule in sort key
42 *         insufficientAccessRights (50), -- refused to return sorted
43 *                                        -- results to this client
44 *         busy                     (51), -- too busy to process
45 *         unwillingToPerform       (53), -- unable to sort
46 *         other                    (80)
47 *         },
48 *     attributeType [0] AttributeDescription OPTIONAL }
49 *
50 *  @author Chad Sikorra <Chad.Sikorra@gmail.com>
51 */
52class SortingResponseControl extends Control
53{
54    /**
55     * @var int
56     */
57    protected $result;
58
59    /**
60     * @var null|string
61     */
62    protected $attribute;
63
64    /**
65     * @param int $result
66     * @param null|string $attribute
67     */
68    public function __construct(int $result, ?string $attribute = null)
69    {
70        $this->result = $result;
71        $this->attribute = $attribute;
72        parent::__construct(self::OID_SORTING_RESPONSE);
73    }
74
75    /**
76     * @return int
77     */
78    public function getResult(): int
79    {
80        return $this->result;
81    }
82
83    /**
84     * @return null|string
85     */
86    public function getAttribute(): ?string
87    {
88        return $this->attribute;
89    }
90
91    /**
92     * {@inheritDoc}
93     * @return Control
94     * @throws EncoderException
95     * @throws PartialPduException
96     */
97    public static function fromAsn1(AbstractType $type)
98    {
99        $sorting = parent::decodeEncodedValue($type);
100        if (!$sorting instanceof SequenceType) {
101            throw new ProtocolException('The server side sorting response is malformed.');
102        }
103        $result = $sorting->getChild(0);
104        $attribute = $sorting->getChild(1);
105        if (!$result instanceof EnumeratedType) {
106            throw new ProtocolException('The server side sorting response is malformed.');
107        }
108
109        $response = new self(
110            $result->getValue(),
111            ($attribute !== null) ? $attribute->getValue() : null
112        );
113
114        return parent::mergeControlData($response, $type);
115    }
116
117    /**
118     * {@inheritdoc}
119     */
120    public function toAsn1(): AbstractType
121    {
122        $this->controlValue = Asn1::sequence(Asn1::enumerated($this->result));
123        if ($this->attribute !== null) {
124            $this->controlValue->addChild(Asn1::context(0, Asn1::octetString($this->attribute)));
125        }
126
127        return parent::toAsn1();
128    }
129}
130