Ldap::setOptions()   D
last analyzed

Complexity

Conditions 9
Paths 9

Size

Total Lines 33
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 4.909
c 0
b 0
f 0
cc 9
eloc 26
nc 9
nop 1
1
<?php
2
declare(strict_types = 1);
3
4
/**
5
 * Micro
6
 *
7
 * @author    Raffael Sahli <[email protected]>
8
 * @copyright Copyright (c) 2017 gyselroth GmbH (https://gyselroth.com)
9
 * @license   MIT https://opensource.org/licenses/MIT
10
 */
11
12
namespace Micro;
13
14
use \Micro\Ldap\Exception;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Micro\Exception.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
15
use \Psr\Log\LoggerInterface;
16
17
class Ldap
18
{
19
    /**
20
     * Connection resource
21
     *
22
     * @var resource
23
     */
24
    protected $connection;
25
26
27
    /**
28
     * Logger
29
     *
30
     * @var Logger
31
     */
32
    protected $logger;
33
34
35
    /**
36
     * URI
37
     *
38
     * @var string
39
     */
40
    protected $uri = 'ldap://127.0.0.1:389';
41
42
43
    /**
44
     * Binddn
45
     *
46
     * @var string
47
     */
48
    protected $binddn;
49
50
51
    /**
52
     * Bindpw
53
     *
54
     * @var string
55
     */
56
    protected $bindpw;
57
58
59
    /**
60
     * Basedn
61
     *
62
     * @var string
63
     */
64
    protected $basedn = '';
65
66
67
    /**
68
     * tls
69
     *
70
     * @var bool
71
     */
72
    protected $tls = false;
73
74
75
    /**
76
     *  Options
77
     *
78
     * @var array
79
     */
80
    protected $options = [];
81
82
83
    /**
84
     * construct
85
     *
86
     * @param   Iterable $config
87
     * @param   Logger $logger
88
     * @return  resource
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
89
     */
90
    public function __construct(LoggerInterface $logger, ?Iterable $config=null)
91
    {
92
        $this->setOptions($config);
93
        $this->logger = $logger;
0 ignored issues
show
Documentation Bug introduced by
It seems like $logger of type object<Psr\Log\LoggerInterface> is incompatible with the declared type object<Micro\Logger> of property $logger.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
94
    }
95
96
97
    /**
98
     * Connect
99
     *
100
     * @return Ldap
101
     */
102
    public function connect(): Ldap
103
    {
104
        $this->logger->debug('connect to ldap server ['.$this->uri.']', [
105
            'category' => get_class($this),
106
        ]);
107
108
        if ($this->binddn === null) {
109
            $this->logger->warning('no binddn set for ldap connection, you should avoid anonymous bind', [
110
                'category' => get_class($this),
111
            ]);
112
        }
113
114
        if ($this->tls === false && substr($this->uri, 0, 5) !== 'ldaps') {
115
            $this->logger->warning('neither tls nor ldaps enabled for ldap connection, it is strongly reccommended to encrypt ldap connections', [
116
                'category' => get_class($this),
117
            ]);
118
        }
119
120
        $this->connection = ldap_connect($this->uri);
121
122
        if ($this->tls === true) {
123
            ldap_start_tls($this->connection);
124
        }
125
126
        foreach ($this->options as $opt => $value) {
127
            ldap_set_option($this->connection, constant($value['attr']), $value['value']);
128
        }
129
130
        if ($this->connection) {
131
            if ($this->binddn !== null) {
132
                $bind = ldap_bind($this->connection, $this->binddn, $this->bindpw);
133
134
                if ($bind) {
135
                    $this->logger->info('bind to ldap server ['.$this->uri.'] with binddn ['.$this->binddn.'] was succesful', [
136
                        'category' => get_class($this),
137
                    ]);
138
139
                    return $this;
140
                } else {
141
                    throw new Exception('failed bind to ldap server, error: '.ldap_error($this->connection));
142
                }
143
            }
144
        } else {
145
            throw new Exception('failed connect to ldap server '.$this->uri);
146
        }
147
148
        return $this;
149
    }
150
151
152
    /**
153
     * Close socket
154
     *
155
     * @return bool
156
     */
157
    public function close(): bool
158
    {
159
        if (is_resource($this->connection)) {
160
            return ldap_unbind($this->connection);
161
        }
162
163
        return true;
164
    }
165
166
167
    /**
168
     * Set options
169
     *
170
     * @param  Iterable $config
171
     * @return Ldap
172
     */
173
    public function setOptions(? Iterable $config = null) : Ldap
174
    {
175
        if ($config === null) {
176
            return $this;
177
        }
178
179
        foreach ($config as $option => $value) {
180
            switch ($option) {
181
                case 'uri':
182
                    $this->uri = (string)$value;
183
                    break;
184
                case 'options':
185
                    $this->options = $value;
186
                    break;
187
                case 'binddn':
188
                    $this->binddn = (string)$value;
189
                    break;
190
                case 'bindpw':
191
                    $this->bindpw = (string)$value;
192
                    break;
193
                case 'basedn':
194
                    $this->basedn = (string)$value;
195
                    break;
196
                case 'tls':
197
                    $this->tls = (bool)(int)$value;
198
                    break;
199
                default:
200
                    throw new Exception('unknown option '.$option.' given');
201
            }
202
        }
203
204
        return $this;
205
    }
206
207
208
    /**
209
     * Get base
210
     *
211
     * @return string
212
     */
213
    public function getBase(): string
214
    {
215
        return $this->basedn;
216
    }
217
218
219
    /**
220
     * Get connection
221
     *
222
     * @return resource
223
     */
224
    public function getResource()
225
    {
226
        if (!is_resource($this->connection)) {
227
            $this->connect();
228
        }
229
230
        return $this->connection;
231
    }
232
}
233