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;
12
13use FreeDSx\Asn1\Type\AbstractType;
14use FreeDSx\Ldap\Entry\Attribute;
15use FreeDSx\Ldap\Entry\Change;
16use FreeDSx\Ldap\Entry\Dn;
17use FreeDSx\Ldap\Entry\Entry;
18use FreeDSx\Ldap\Entry\Rdn;
19use FreeDSx\Ldap\Operation\Request\AbandonRequest;
20use FreeDSx\Ldap\Operation\Request\AddRequest;
21use FreeDSx\Ldap\Operation\Request\AnonBindRequest;
22use FreeDSx\Ldap\Operation\Request\CancelRequest;
23use FreeDSx\Ldap\Operation\Request\CompareRequest;
24use FreeDSx\Ldap\Operation\Request\DeleteRequest;
25use FreeDSx\Ldap\Operation\Request\ExtendedRequest;
26use FreeDSx\Ldap\Operation\Request\ModifyDnRequest;
27use FreeDSx\Ldap\Operation\Request\ModifyRequest;
28use FreeDSx\Ldap\Operation\Request\PasswordModifyRequest;
29use FreeDSx\Ldap\Operation\Request\SaslBindRequest;
30use FreeDSx\Ldap\Operation\Request\SearchRequest;
31use FreeDSx\Ldap\Operation\Request\SimpleBindRequest;
32use FreeDSx\Ldap\Operation\Request\UnbindRequest;
33use FreeDSx\Ldap\Protocol\ProtocolElementInterface;
34use FreeDSx\Ldap\Search\Filter\FilterInterface;
35use FreeDSx\Ldap\Search\Filters;
36
37/**
38 * Provides a set of factory methods to help quickly construct different operations/requests.
39 *
40 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
41 */
42class Operations
43{
44    /**
45     * A request to abandon an ongoing operation.
46     *
47     * @param int $id
48     * @return AbandonRequest
49     */
50    public static function abandon(int $id)
51    {
52        return new AbandonRequest($id);
53    }
54
55    /**
56     * Add an entry to LDAP.
57     *
58     * @param Entry $entry
59     * @return AddRequest
60     */
61    public static function add(Entry $entry)
62    {
63        return new AddRequest($entry);
64    }
65
66    /**
67     * A simple bind request with a username and password.
68     *
69     * @param string $username
70     * @param string $password
71     * @return SimpleBindRequest
72     */
73    public static function bind(string $username, string $password)
74    {
75        return new SimpleBindRequest($username, $password);
76    }
77
78    /**
79     * A SASL bind request with a specific mechanism and their associated options.
80     *
81     * @param array $options
82     * @param string $mechanism
83     * @param string|null $credentials
84     * @return SaslBindRequest
85     */
86    public static function bindSasl(array $options = [], string $mechanism = '', ?string $credentials = null)
87    {
88        return new SaslBindRequest($mechanism, $credentials, $options);
89    }
90
91    /**
92     * An anonymous bind request.
93     *
94     * @param string $username
95     * @return AnonBindRequest
96     */
97    public static function bindAnonymously(string $username = '')
98    {
99        return new AnonBindRequest($username);
100    }
101
102    /**
103     * Cancel a specific operation. Pass either the message ID or the LdapMessage object.
104     */
105    public static function cancel(int $messageId): CancelRequest
106    {
107        return new CancelRequest($messageId);
108    }
109
110    /**
111     * A comparison operation to check if an entry has an attribute with a certain value.
112     *
113     * @return CompareRequest
114     */
115    public static function compare(string $dn, string $attributeName, string $value): CompareRequest
116    {
117        return new CompareRequest($dn, Filters::equal($attributeName, $value));
118    }
119
120    /**
121     * Delete an entry from LDAP by its DN.
122     */
123    public static function delete(string $dn): DeleteRequest
124    {
125        return new DeleteRequest($dn);
126    }
127
128    /**
129     * Perform an extended operation.
130     *
131     * @param null|AbstractType|ProtocolElementInterface|string $value
132     */
133    public static function extended(string $name, $value = null): ExtendedRequest
134    {
135        return new ExtendedRequest($name, $value);
136    }
137
138    /**
139     * Perform modification(s) on an LDAP entry.
140     */
141    public static function modify(string $dn, Change ...$changes): ModifyRequest
142    {
143        return new ModifyRequest($dn, ...$changes);
144    }
145
146    /**
147     * Move an LDAP entry to a new parent DN location.
148     */
149    public static function move(string $dn, string $newParentDn): ModifyDnRequest
150    {
151        $dnObj = new Dn($dn);
152
153        return new ModifyDnRequest($dn, $dnObj->getRdn()->toString(), true, $newParentDn);
154    }
155
156    /**
157     * Creates a password modify extended operation.
158     */
159    public static function passwordModify(string $username, string $oldPassword, string $newPassword): PasswordModifyRequest
160    {
161        return new PasswordModifyRequest($username, $oldPassword, $newPassword);
162    }
163
164    /**
165     * Quit is an alias for unbind. This is more indicative of what an unbind actually does.
166     */
167    public static function quit(): UnbindRequest
168    {
169        return self::unbind();
170    }
171
172    /**
173     * Rename an LDAP entry by modifying its RDN.
174     *
175     * @param string|Rdn $rdn
176     */
177    public static function rename(string $dn, $rdn, bool $deleteOldRdn = true): ModifyDnRequest
178    {
179        return new ModifyDnRequest($dn, $rdn, $deleteOldRdn);
180    }
181
182    /**
183     * Search LDAP with a given filter, scope, etc to retrieve a set of entries.
184     *
185     * @param string[]|Attribute[] ...$attributes
186     */
187    public static function search(FilterInterface $filter, ...$attributes): SearchRequest
188    {
189        return new SearchRequest($filter, ...$attributes);
190    }
191
192    /**
193     * Search for a specific base DN object to read. This sets a 'present' filter for the 'objectClass' attribute to help
194     * simplify it.
195     *
196     * @param array ...$attributes
197     */
198    public static function read(string $baseDn, ...$attributes): SearchRequest
199    {
200        return (new SearchRequest(Filters::present('objectClass'), ...$attributes))->base($baseDn)->useBaseScope();
201    }
202
203    /**
204     * Search a single level list from a base DN object.
205     *
206     * @param array ...$attributes
207     */
208    public static function list(FilterInterface $filter, string $baseDn, ...$attributes): SearchRequest
209    {
210        return (new SearchRequest($filter, ...$attributes))->base($baseDn)->useSingleLevelScope();
211    }
212
213    /**
214     * A request to unbind. This actually causes the server to terminate the client connection.
215     *
216     * @return UnbindRequest
217     */
218    public static function unbind(): UnbindRequest
219    {
220        return new UnbindRequest();
221    }
222
223    /**
224     * A request to determine who is currently authorized against LDAP for the current session.
225     *
226     * @return ExtendedRequest
227     */
228    public static function whoami(): ExtendedRequest
229    {
230        return new ExtendedRequest(ExtendedRequest::OID_WHOAMI);
231    }
232}
233