Completed
Push — master ( f22a46...046041 )
by Patrick
02:27 queued 12s
created

LDAPGroup::setDescription()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Flipside\Auth;
3
4
class LDAPGroup extends Group
5
{
6
    use LDAPCachableObject;
7
8
    private $ldapObj;
9
    private $server;
10
11
    /**
12
     * Initialize a LDAPGroup object
13
     *
14
     * @SuppressWarnings("StaticAccess")
15
     */
16
    public function __construct($data)
17
    {
18
        $this->server = \Flipside\LDAP\LDAPServer::getInstance();
19
        $this->initialize($data);
20
    }
21
22
    public function getGroupName()
23
    {
24
        return $this->getFieldSingleValue('cn');
25
    }
26
27
    public function getDescription()
28
    {
29
        return $this->getFieldSingleValue('description');
30
    }
31
32
    public function setDescription($name)
33
    {
34
        return $this->setField('description', $name);
35
    }
36
37
    private function getMembersField(&$fieldName = false)
38
    {
39
        $rawMembers = $this->getField('member');
40
        $fieldName  = 'member';
41
        if($rawMembers === false)
42
        {
43
            $rawMembers = $this->getField('uniqueMember');
44
            $fieldName  = 'uniqueMember';
45
        }
46
        if($rawMembers === false)
47
        {
48
            $rawMembers = $this->getField('memberUid');
49
            $fieldName  = 'memberUid';
50
        }
51
        if(!isset($rawMembers['count']))
52
        {
53
            $rawMembers['count'] = count($rawMembers);
54
        }
55
        return $rawMembers;
56
    }
57
58
    private function getIDFromDN($distinguishedName)
59
    {
60
        $split = explode(',', $distinguishedName);
61
        if(strncmp('cn=', $split[0], 3) === 0)
62
        {
63
            return substr($split[0], 3);
64
        }
65
        return substr($split[0], 4);
66
    }
67
68
    public function getMemberUids($recursive = true)
69
    {
70
        $members = array();
71
        $rawMembers = $this->getMembersField();
72
        for($i = 0; $i < $rawMembers['count']; $i++)
73
        {
74
            if($recursive && strncmp($rawMembers[$i], 'cn=', 3) === 0)
75
            {
76
                $child = new LDAPGroup($rawMembers[$i]);
77
                if($child !== false)
78
                {
79
                    $members = array_merge($members, $child->members());
80
                }
81
            }
82
            else
83
            {
84
                array_push($members, $rawMembers[$i]);
85
            }
86
        }
87
        $count = count($members);
88
        for($i = 0; $i < $count; $i++)
89
        {
90
            $members[$i] = $this->getIDFromDN($members[$i]);
91
        }
92
        return $members;
93
    }
94
95
    private function getObjectFromDN($distinguishedName)
96
    {
97
        $split = explode(',', $distinguishedName);
98
        if(strncmp('cn=', $distinguishedName, 3) === 0)
99
        {
100
            if(count($split) === 1)
101
            {
102
                return LDAPGroup::from_name($distinguishedName, $this->server);
103
            }
104
            return LDAPGroup::from_name(substr($split[0], 3), $this->server);
105
        }
106
        if(count($split) === 1)
107
        {
108
            return LDAPUser::from_name($distinguishedName, $this->server);
109
        }
110
        return LDAPUser::from_name(substr($split[0], 4), $this->server);
111
    }
112
113
    private function getMemberDetail($members)
114
    {
115
        $details = array();
116
        $count = count($members);
117
        for($i = 0; $i < $count; $i++)
118
        {
119
            $details[$i] = $this->getObjectFromDN($members[$i]);
120
        }
121
        return $details;
122
    }
123
124
    public function members($details = false, $recursive = true, $includeGroups = true)
125
    {
126
        $members = array();
127
        $rawMembers = $this->getMembersField();
128
        $count = $rawMembers['count'];
129
        for($i = 0; $i < $count; $i++)
130
        {
131
            $rawMember = array_pop($rawMembers);
132
            if($recursive && strncmp($rawMember, 'cn=', 3) === 0)
133
            {
134
                $child = new LDAPGroup($rawMember);
135
                if($child !== false)
136
                {
137
                    $members = array_merge($members, $child->members(false, $recursive, $includeGroups));
138
                }
139
            }
140
            else if($includeGroups !== false || strncmp($rawMember, 'cn=', 3) !== 0)
141
            {
142
                array_push($members, $rawMember);
143
            }
144
        }
145
        if($details === true)
146
        {
147
            $members = $this->getMemberDetail($members);
148
        }
149
        return $members;
150
    }
151
152
    public function getNonMembers($select = false)
153
    {
154
        $data = array();
155
        $groupFilter = '(&(cn=*)(!(cn='.$this->getGroupName().'))';
156
        $userFilter = '(&(cn=*)';
157
        $members = $this->members();
158
        $count = count($members);
159
        for($i = 0; $i < $count; $i++)
160
        {
161
            $dnComps = explode(',', $members[$i]);
162
            if(strncmp($members[$i], "uid=", 4) == 0)
163
            {
164
                $userFilter .= '(!('.$dnComps[0].'))';
165
            }
166
            else
167
            {
168
                $groupFilter .= '(!('.$dnComps[0].'))';
169
            }
170
        }
171
        $userFilter .= ')';
172
        $groupFilter .= ')';
173
        $groups = $this->server->read($this->server->group_base, $groupFilter);
174
        $count = count($groups);
175
        for($i = 0; $i < $count; $i++)
176
        {
177
            if($groups[$i] === false || $groups[$i] === null)
178
            {
179
                continue;
180
            }
181
            array_push($data, new LDAPGroup($groups[$i]));
182
        }
183
        $users = $this->server->read($this->server->user_base, $userFilter, false, $select);
184
        $count = count($users);
185
        for($i = 0; $i < $count; $i++)
186
        {
187
            array_push($data, new LDAPUser($users[$i]));
188
        } 
189
        return $data;
190
    }
191
192
    public function clearMembers()
193
    {
194
        if(isset($this->ldapObj['member']))
195
        {
196
            $this->ldapObj['member'] = array();
197
        }
198
        else if(isset($this->ldapObj['uniquemember']))
199
        {
200
            $this->ldapObj['uniquemember'] = array();
201
        }
202
        else if(isset($this->ldapObj['memberuid']))
203
        {
204
            $this->ldapObj['memberuid'] = array();
205
        }
206
    }
207
208
    public function addMember($name, $isGroup = false, $flush = true)
209
    {
210
        $auth = \Flipside\AuthProvider::getInstance();
211
        $ldap = $auth->getMethodByName('Flipside\Auth\LDAPAuthenticator');
212
        if($ldap !== false)
213
        {
214
            $this->server = $ldap->getAndBindServer(true);
215
        }
216
        $distinguishedName = 'uid='.$name.','.$this->server->user_base;
217
        if($isGroup)
218
        {
219
            $distinguishedName = 'cn='.$name.','.$this->server->group_base;
220
        }
221
        $propName   = false;
222
        $rawMembers = $this->getMembersField($propName);
223
        if(isset($rawMembers['count']))
224
        {
225
            unset($rawMembers['count']);
226
        }
227
        if(in_array($distinguishedName, $rawMembers) || in_array($name, $rawMembers))
228
        {
229
            return true;
230
        }
231
        if($propName === 'memberUid')
232
        {
233
            if($isGroup)
234
            {
235
                throw new \Exception('Unable to add a group as a child of this group type');
236
            }
237
            array_push($rawMembers, $name);
238
        }
239
        else
240
        {
241
            array_push($rawMembers, $distinguishedName);
242
        }
243
        $tmp = strtolower($propName);
244
        $this->ldapObj->$tmp = $rawMembers;
245
        if($flush === true)
246
        {
247
            $obj = array('dn'=>$this->ldapObj->dn);
248
            $obj[$propName] = $rawMembers;
249
            return $this->server->update($obj);
250
        }
251
        else
252
        {
253
            return true;
254
        }
255
    }
256
257
    /**
258
     * @param string $name The Group Name
259
     * @param boolean|\LDAP\LDAPServer $data The server to read from
260
     */
261
    public static function from_name($name, $data = false)
262
    {
263
        if($data === false)
264
        {
265
            throw new \Exception('data must be set for LDAPGroup');
266
        }
267
        $filter = new \Data\Filter("cn eq $name");
268
        $group = $data->read($data->group_base, $filter);
269
        if($group === false || !isset($group[0]))
270
        {
271
            return null;
272
        }
273
        return new static($group[0]);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new static($group[0]); (Flipside\Auth\LDAPGroup) is incompatible with the return type of the parent method Flipside\Auth\Group::from_name of type boolean|Auth\Group.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
274
    }
275
}
276
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
277