Passed
Push — master ( 11fb63...ed1d12 )
by Petr
02:48
created

Ldap::bindUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
namespace kalanis\kw_mapper\Storage\Database\Raw;
4
5
6
use kalanis\kw_mapper\Interfaces\IPassConnection;
7
use kalanis\kw_mapper\MapperException;
8
use kalanis\kw_mapper\Storage\Database\ADatabase;
9
use kalanis\kw_mapper\Storage\Database\Dialects;
10
use kalanis\kw_mapper\Storage\Database\TConnection;
11
12
13
/**
14
 * Class Ldap
15
 * @package kalanis\kw_mapper\Storage\Database\Raw
16
 * Lightweight directory access protocol
17
 * @link https://www.php.net/manual/en/function.ldap-bind
18
 * @link https://www.geekshangout.com/php-example-get-data-active-directory-via-ldap/
19
 * @link https://github.com/etianen/django-python3-ldap/blob/master/django_python3_ldap/ldap.py
20
 * @link https://github.com/django-auth-ldap/django-auth-ldap/blob/master/django_auth_ldap/backend.py
21
 * @codeCoverageIgnore remote connection
22
 */
23
class Ldap extends ADatabase implements IPassConnection
24
{
25
    use TConnection;
26
27
    protected $extension = 'ldap';
28
    /** @var resource|null */
29
    protected $connection = null;
30
31
    public function languageDialect(): string
32
    {
33
        return Dialects\EmptyDialect::class;
34
    }
35
36
    public function disconnect(): void
37
    {
38
        if ($this->isConnected()) {
39
            ldap_unbind($this->connection);
0 ignored issues
show
Bug introduced by
It seems like $this->connection can also be of type object; however, parameter $ldap of ldap_unbind() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
            ldap_unbind(/** @scrutinizer ignore-type */ $this->connection);
Loading history...
40
        }
41
        $this->connection = null;
42
    }
43
44
    /**
45
     * @param bool $withBind
46
     * @throws MapperException
47
     */
48
    public function connect(bool $withBind = true): void
49
    {
50
        if (!$this->isConnected()) {
51
            $this->connection = $this->connectToServer();
52
            if ($withBind) {
53
                $this->bindUser($this->config->getUser(), $this->config->getPassword());
54
            }
55
        }
56
    }
57
58
    /**
59
     * @throws MapperException
60
     * @return resource
61
     */
62
    protected function connectToServer()
63
    {
64
        $connection = ldap_connect($this->config->getLocation());
65
66
        if (false === $connection) {
67
            throw new \RuntimeException('Ldap connection error.');
68
        }
69
70
        if ( false !== strpos($this->config->getLocation(), 'ldaps://' )) {
71
            if (!ldap_start_tls($connection)) {
72
                throw new MapperException('Cannot start TLS for secured connection!');
73
            }
74
        }
75
        // Go with LDAP version 3 if possible (needed for renaming and Novell schema fetching)
76
        ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
77
        // We need this for doing a LDAP search.
78
        ldap_set_option($connection, LDAP_OPT_REFERRALS, 0);
79
80
        return $connection;
81
    }
82
83
    /**
84
     * @param string $domain
85
     * @param array<string|int, int|string|float|null> $changed
86
     * @throws MapperException
87
     * @return bool
88
     */
89
    public function add(string $domain, array $changed): bool
90
    {
91
        return ldap_add($this->getConnection(), $domain, $changed);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_add() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
        return ldap_add(/** @scrutinizer ignore-type */ $this->getConnection(), $domain, $changed);
Loading history...
92
    }
93
94
    /**
95
     * @param string $domain
96
     * @param array<string|int, int|string|float|null> $changed
97
     * @throws MapperException
98
     * @return bool
99
     */
100
    public function replace(string $domain, array $changed): bool
101
    {
102
        return ldap_mod_replace($this->getConnection(), $domain, $changed);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_mod_replace() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

102
        return ldap_mod_replace(/** @scrutinizer ignore-type */ $this->getConnection(), $domain, $changed);
Loading history...
103
    }
104
105
    /**
106
     * @param string $domain
107
     * @throws MapperException
108
     * @return bool
109
     */
110
    public function delete(string $domain): bool
111
    {
112
        return ldap_delete($this->getConnection(), $domain);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_delete() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
        return ldap_delete(/** @scrutinizer ignore-type */ $this->getConnection(), $domain);
Loading history...
113
    }
114
115
    /**
116
     * @param string $domain
117
     * @param string $filter
118
     * @throws MapperException
119
     * @return array<string|int, string|int|float|array<string|int|float>>
120
     */
121
    public function search(string $domain, string $filter): array
122
    {
123
        $result = ldap_search($this->getConnection(), $domain, $filter);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_search() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
        $result = ldap_search(/** @scrutinizer ignore-type */ $this->getConnection(), $domain, $filter);
Loading history...
124
        if (false === $result) {
125
            return [];
126
        }
127
128
        $items = ldap_get_entries($this->getConnection(), $result);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_get_entries() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

128
        $items = ldap_get_entries(/** @scrutinizer ignore-type */ $this->getConnection(), $result);
Loading history...
129
        if (false === $items) {
130
            return [];
131
        }
132
133
        return $items;
134
    }
135
136
    /**
137
     * @param string $domain
138
     * @param string $pass
139
     * @throws MapperException
140
     * @return bool
141
     */
142
    public function bindUser(string $domain, string $pass): bool
143
    {
144
        return ldap_bind($this->getConnection(), $domain, $pass);
0 ignored issues
show
Bug introduced by
It seems like $this->getConnection() can also be of type object; however, parameter $ldap of ldap_bind() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
        return ldap_bind(/** @scrutinizer ignore-type */ $this->getConnection(), $domain, $pass);
Loading history...
145
    }
146
147
    /**
148
     * @throws MapperException
149
     * @return string
150
     */
151
    public function getDomain(): string
152
    {
153
        if (!isset($this->attributes['domain'])) {
154
            throw new MapperException('The domain is not set!');
155
        }
156
        return strval($this->attributes['domain']);
157
    }
158
}
159