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;
13
14use FreeDSx\Ldap\Exception\UrlParseException;
15use function explode;
16use function str_ireplace;
17use function str_replace;
18use function substr;
19
20/**
21 * Represents a LDAP URL extension component. RFC 4516, Section 2.
22 *
23 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
24 */
25class LdapUrlExtension
26{
27    use LdapUrlTrait;
28
29    /**
30     * @var string
31     */
32    protected $name;
33
34    /**
35     * @var null|string
36     */
37    protected $value;
38
39    /**
40     * @var bool
41     */
42    protected $isCritical = false;
43
44    /**
45     * @param string $name
46     * @param null|string $value
47     * @param bool $isCritical
48     */
49    public function __construct(string $name, ?string $value = null, bool $isCritical = false)
50    {
51        $this->name = $name;
52        $this->value = $value;
53        $this->isCritical = $isCritical;
54    }
55
56    /**
57     * @return string
58     */
59    public function getName(): string
60    {
61        return $this->name;
62    }
63
64    /**
65     * @param string $name
66     * @return $this
67     */
68    public function setName(string $name)
69    {
70        $this->name = $name;
71
72        return $this;
73    }
74
75    /**
76     * @return null|string
77     */
78    public function getValue(): ?string
79    {
80        return $this->value;
81    }
82
83    /**
84     * @param null|string $value
85     * @return $this
86     */
87    public function setValue(?string $value)
88    {
89        $this->value = $value;
90
91        return $this;
92    }
93
94    public function getIsCritical(): bool
95    {
96        return $this->isCritical;
97    }
98
99    /**
100     * @param bool $isCritical
101     * @return $this
102     */
103    public function setIsCritical(bool $isCritical)
104    {
105        $this->isCritical = $isCritical;
106
107        return $this;
108    }
109
110    /**
111     * @return string
112     */
113    public function toString(): string
114    {
115        $ext = ($this->isCritical ? '!' : '') . str_replace(',', '%2c', self::encode($this->name));
116
117        if ($this->value !== null) {
118            $ext .= '=' . str_replace(',', '%2c', self::encode($this->value));
119        }
120
121        return $ext;
122    }
123
124    /**
125     * @return string
126     */
127    public function __toString()
128    {
129        return $this->toString();
130    }
131
132    /**
133     * @param string $extension
134     * @return LdapUrlExtension
135     * @throws UrlParseException
136     */
137    public static function parse(string $extension): LdapUrlExtension
138    {
139        if (preg_match('/!?\w+(=.*)?/', $extension) !== 1) {
140            throw new UrlParseException(sprintf('The LDAP URL extension is malformed: %s', $extension));
141        }
142        $pieces = explode('=', $extension, 2);
143
144        $isCritical = isset($pieces[0][0]) && $pieces[0][0] === '!';
145        if ($isCritical) {
146            $pieces[0] = substr($pieces[0], 1);
147        }
148
149        $name = str_ireplace('%2c', ',', self::decode($pieces[0]));
150        $value = isset($pieces[1]) ? str_ireplace('%2c', ',', self::decode($pieces[1])) : null;
151
152        return new self($name, $value, $isCritical);
153    }
154}
155