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\Search\Filter;
13
14use FreeDSx\Asn1\Asn1;
15use FreeDSx\Asn1\Exception\EncoderException;
16use FreeDSx\Asn1\Type\AbstractType;
17use FreeDSx\Asn1\Type\IncompleteType;
18use FreeDSx\Asn1\Type\SequenceType;
19use FreeDSx\Ldap\Exception\ProtocolException;
20use FreeDSx\Ldap\Exception\RuntimeException;
21use FreeDSx\Ldap\Protocol\Factory\FilterFactory;
22use FreeDSx\Ldap\Protocol\LdapEncoder;
23
24/**
25 * Represents the negation of a filter. RFC 4511, 4.5.1
26 *
27 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
28 */
29class NotFilter implements FilterInterface
30{
31    protected const CHOICE_TAG = 2;
32
33    /**
34     * @var FilterInterface
35     */
36    protected $filter;
37
38    /**
39     * @param FilterInterface $filter
40     */
41    public function __construct(FilterInterface $filter)
42    {
43        $this->filter = $filter;
44    }
45
46    /**
47     * @return FilterInterface
48     */
49    public function get(): FilterInterface
50    {
51        return $this->filter;
52    }
53
54    /**
55     * @param FilterInterface $filter
56     * @return $this
57     */
58    public function set(FilterInterface $filter)
59    {
60        $this->filter = $filter;
61
62        return $this;
63    }
64
65    /**
66     * {@inheritdoc}
67     */
68    public function toAsn1(): AbstractType
69    {
70        return Asn1::context(self::CHOICE_TAG, Asn1::sequence($this->filter->toAsn1()));
71    }
72
73    /**
74     * {@inheritdoc}
75     */
76    public function toString(): string
77    {
78        return self::PAREN_LEFT
79            . self::OPERATOR_NOT
80            . $this->filter->toString()
81            . self::PAREN_RIGHT;
82    }
83
84    /**
85     * @return string
86     */
87    public function __toString()
88    {
89        return $this->toString();
90    }
91
92    /**
93     * {@inheritDoc}
94     * @param AbstractType $type
95     * @return NotFilter
96     * @throws ProtocolException
97     * @throws EncoderException
98     * @throws RuntimeException
99     */
100    public static function fromAsn1(AbstractType $type)
101    {
102        $type = $type instanceof IncompleteType ? (new LdapEncoder())->complete($type, AbstractType::TAG_TYPE_SEQUENCE) : $type;
103        if (!($type instanceof SequenceType && count($type) === 1)) {
104            throw new ProtocolException('The not filter is malformed');
105        }
106        $child = $type->getChild(0);
107        if ($child === null) {
108            throw new ProtocolException('The "not" filter is malformed.');
109        }
110
111        return new self(FilterFactory::get($child));
112    }
113}
114