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