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

User::isProfileComplete()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 2
nop 0
dl 0
loc 10
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * User class
4
 *
5
 * This file describes the User classes
6
 *
7
 * PHP version 5 and 7
8
 *
9
 * @author Patrick Boyd / [email protected]
10
 * @copyright Copyright (c) 2015, Austin Artistic Reconstruction
11
 * @license http://www.apache.org/licenses/ Apache 2.0 License
12
 */
13
14
namespace Flipside\Auth;
15
16
/**
17
 * A class to abstract access to Users regardless of the Authentication type used.
18
 *
19
 * This class is the primary method to access user information.
20
 * 
21
 * @property string $uid The user's ID or name
22
 * @property string $mail The user's email address
23
 * @property string $sn The user's surname (last name)
24
 * @property string $givenName The user's given name (first name)
25
 * @property string $cn The user's nick name
26
 * @property string $displayName The user's display name
27
 * @property string $postalAddress The user's mailing address
28
 * @property string $postalCode The user's postal or zip code
29
 * @property string $l The user's city
30
 * @property string $st The user's state or province
31
 * @property string $c The user's country
32
 * @property string $mobile The user's phone number
33
 * @property string $jpegPhoto The user's profile photo
34
 * @property array $host The service's the user can use to login
35
 * @property array $title The user's titles in the organization
36
 * @property string $o The user's organization
37
 * @property array $ou The user's units or areas within the organization
38
 */
39
class User extends \Flipside\SerializableObject
40
{
41
    /**
42
     * An array to cache the title to string mappings so that they don't need to be pulled from the database
43
     * everytime
44
     */ 
45
    public static $titlenames = null;
46
47
    /**
48
     * An array of properties that cannot be set on a user
49
     */
50
    protected $unsettableElements = array(
51
        'uid',
52
        'email'
53
    );
54
55
    /**
56
     * Is this user in the Group or a child of that group?
57
     *
58
     * @param string $name The name of the group to check if the user is in
59
     *
60
     * @return boolean True if the user is in the group, false otherwise
61
     */
62
    public function isInGroupNamed($name)
63
    {
64
        return false;
65
    }
66
67
    public function __get($propName)
68
    {
69
        return false;
70
    }
71
72
    public function __set($propName, $value)
73
    {
74
    }
75
76
    public function __isset($propName)
77
    {
78
        return false;
79
    }
80
81
    /**
82
     * The list of titles for the user
83
     *
84
     * @return boolean|array The user's title(s) in user friendly strings
85
     *
86
     * @SuppressWarnings("StaticAccess")
87
     */
88
    public function getTitleNames()
89
    {
90
        $titles = $this->title;
91
        if($titles === false)
92
        {
93
            return false;
94
        }
95
        if(self::$titlenames === null)
96
        {
97
            $dataSet = \DataSetFactory::getDataSetByName('profiles');
98
            $dataTable = $dataSet['position'];
99
            $titlenames = $dataTable->read();
100
            self::$titlenames = array();
101
            $count = count($titlenames);
102
            for($i = 0; $i < $count; $i++)
103
            {
104
                self::$titlenames[$titlenames[$i]['short_name']] = $titlenames[$i];
105
            }
106
        }
107
        $count = count($titles);
108
        for($i = 0; $i < $count; $i++)
109
        {
110
            if(isset(self::$titlenames[$titles[$i]]))
111
            {
112
                $title = self::$titlenames[$titles[$i]];
113
                $titles[$i] = $title['name'];
114
            }
115
        }
116
        return $titles;
117
    }
118
119
    /**
120
     * The groups the user is a part of
121
     *
122
     * @return boolean|array The user's Auth\Group structures
123
     */
124
    public function getGroups()
125
    {
126
        return false;
127
    }
128
129
    /**
130
     * Add a supplemental login type that the user can use to login
131
     *
132
     * @param string $provider The hostname for the provider
133
     */
134
    public function addLoginProvider($provider)
135
    {
136
        if(isset($this->host))
137
        {
138
            $tmp = $this->host;
139
            $tmp[] = $provider;
140
            $this->host = $tmp;
141
        }
142
        else
143
        {
144
            $this->host = array($provider);
145
        }
146
    }
147
148
    /**
149
     * Can the user login with this provider?
150
     *
151
     * @param string $provider The hostname for the provider
152
     *
153
     * @return boolean true if they can login with the provider, false otherwise
154
     */
155
    public function canLoginWith($provider)
156
    {
157
        $hosts = $this->host;
158
        if($hosts === false)
159
        {
160
            return false;
161
        }
162
        $count = count($hosts);
163
        for($i = 0; $i < $count; $i++)
164
        {
165
            if(strcasecmp($hosts[$i], $provider) === 0)
166
            {
167
                return true;
168
            }
169
        }
170
        return false;
171
    }
172
173
    /**
174
     * Set the user's password without verifying the current password
175
     *
176
     * @param string $password The new user password
177
     *
178
     * @return boolean true if the user's password was changed, false otherwise
179
     */
180
    protected function setPass($password)
181
    {
182
        return false;
183
    }
184
185
    /**
186
     * Has the user completely filled out their user profile?
187
     *
188
     * @return boolean true if the user's profile is complete, false otherwise
189
     */
190
    public function isProfileComplete()
191
    {
192
        if($this->c === false || $this->postalAddress === false ||
193
           $this->postalCode === false || $this->l === false ||
194
           $this->st === false || $this->mobile === false)
195
        {
196
            return false;
197
        }
198
        return true;
199
    }
200
201
    /**
202
     * Validate that the user's password is the specified password
203
     *
204
     * @param string $password The user's current password
205
     *
206
     * @return boolean true if the user's password is correct, false otherwise
207
     *
208
     * @SuppressWarnings("UnusedFormalParameter")
209
     */
210
    public function validate_password($password)
211
    {
212
        return false;
213
    }
214
215
    /**
216
     * Validate that the user's reset hash is the sepcified hash
217
     *
218
     * @param string $hash The user's reset hash
219
     *
220
     * @return boolean true if the user's hash is correct, false otherwise
221
     *
222
     * @SuppressWarnings("UnusedFormalParameter")
223
     */
224
    public function validate_reset_hash($hash)
225
    {
226
        return false;
227
    }
228
229
    /**
230
     * Change the user's password, validating the old password or reset hash
231
     *
232
     * @param string $oldpass The user's original password or reset hash if $isHash is true
233
     * @param string $newpass The user's new password
234
     * @param boolean $isHash Is $old_pass a password or a hash
235
     *
236
     * @return boolean true if the user's password was changed, false otherwise
237
     */
238
    public function change_pass($oldpass, $newpass, $isHash = false)
239
    {
240
        if($isHash === false && $this->validate_password($oldpass) === false)
241
        {
242
            throw new \Exception('Invalid Password!', 3);
243
        }
244
        if($isHash === true && $this->validate_reset_hash($oldpass) === false)
245
        {
246
            throw new \Exception('Invalid Reset Hash!', 3);
247
        }
248
        if($this->setPass($newpass) === false)
249
        {
250
            throw new \Exception('Unable to set password!', 6);
251
        }
252
        return true;
253
    }
254
255
    /**
256
     * Allow write for the user
257
     */
258
    protected function enableReadWrite()
259
    {
260
    }
261
262
    /**
263
     * Update the user password if required
264
     */
265
    private function editUserPassword(&$data)
266
    {
267
        if(isset($data->password))
268
        {
269 View Code Duplication
            if(isset($data->oldpass))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
270
            {
271
                $this->change_pass($data->oldpass, $data->password);
272
                unset($data->oldpass);
273
            }
274
            else if(isset($data->hash))
275
            {
276
                $this->change_pass($data->hash, $data->password, true);
277
                unset($data->hash);
278
            }
279
            unset($data->password);
280
        }
281
        else if(isset($data->userPassword))
282
        {
283 View Code Duplication
            if(isset($data->oldpass))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
284
            {
285
                $this->change_pass($data->oldpass, $data->userPassword);
286
                unset($data->oldpass);
287
            }
288
            else if(isset($data->hash))
289
            {
290
                $this->change_pass($data->hash, $data->userPassword, true);
291
                unset($data->hash);
292
            }
293
            unset($data->userPassword);
294
        }
295
    }
296
297
    private function checkForUnsettableElements($data)
298
    {
299
        $count = count($this->unsettableElements);
300
        for($i = 0; $i < $count; $i++)
301
        {
302
            $propName = $this->unsettableElements[$i];
303
            if(isset($data->{$propName}))
304
            {
305
                if($data->{$propName} !== $this->{$propName})
306
                {
307
                    throw new \Exception('Unable to change '.$propName.'!');
308
                }
309
                unset($data->{$propName});
310
            }
311
        }
312
    }
313
314
    /**
315
     * Modify the user given the provided data object
316
     *
317
     * @param stdClass $data The user's new data
318
     *
319
     * @return boolean true if the user's data was changed, false otherwise
320
     */
321
    public function editUser($data)
322
    {
323
        if(is_array($data))
324
        {
325
            $data = new \Flipside\SerializableObject($data);
326
        }
327
328
        $this->checkForUnsettableElements($data);
329
330
        $this->enableReadWrite();
331
332
        /* These elements require special handling */
333
        $this->editUserPassword($data);
334
        if(isset($data->jpegPhoto))
335
        {
336
            $this->jpegPhoto = base64_decode($data->jpegPhoto);
337
            unset($data->jpegPhoto);
338
        }
339
340
        /* These are generic elements */
341
        if(!is_array($data))
342
        {
343
            $data = get_object_vars($data);
344
        }
345
        foreach($data as $key=>$value)
346
        {
347
            $this->{$key} = $value;
348
        }
349
    }
350
351
    /**
352
     * Obtain the user's password reset hash
353
     *
354
     * @return string|false A hash if available, false otherwise
355
     */
356
    public function getPasswordResetHash()
357
    {
358
        return false;
359
    }
360
361
    /**
362
     * Remove the email address from the user account
363
     *
364
     * @param string $email The email to remove
365
     *
366
     * @return boolean If the operation succeeded or not
367
     */
368
    public function removeEmail($email)
369
    {
370
        return false;
371
    }
372
373
    /**
374
     * Serialize the user data into a format usable by the json_encode method
375
     *
376
     * @return array A simple keyed array representing the user
377
     */
378
    public function jsonSerialize()
379
    {
380
        $user = array();
381
        $user['displayName'] = $this->displayName;
382
        $user['givenName'] = $this->givenName;
383
        $user['jpegPhoto'] = base64_encode($this->jpegPhoto);
384
        $user['mail'] = $this->mail;
385
        $user['mobile'] = $this->mobile;
386
        $user['uid'] = $this->uid;
387
        $user['o'] = $this->o;
388
        $user['title'] = $this->title;
389
        $user['titlenames'] = $this->getTitleNames();
390
        $user['st'] = $this->st;
391
        $user['l'] = $this->l;
392
        $user['sn'] = $this->sn;
393
        $user['cn'] = $this->cn;
394
        $user['postalAddress'] = $this->postalAddress;
395
        $user['postalCode'] = $this->postalCode;
396
        $user['c'] = $this->c;
397
        $user['ou'] = $this->ou;
398
        $user['host'] = $this->host;
399
        $user['class'] = get_class($this);
400
        if(isset($this->allMail))
401
        {
402
            $user['allMail'] = $this->allMail;
0 ignored issues
show
Documentation introduced by
The property allMail does not exist on object<Flipside\Auth\User>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
403
        }
404
        return $user;
405
    }
406
407
    /**
408
     * Serialize the user data into a VCARD 2.1 format
409
     *
410
     * @return string The VCARD for the user
411
     */
412
    public function getVcard()
413
    {
414
        $ret = "BEGIN:VCARD\nVERSION:2.1\n";
415
        $ret .= 'N:'.$this->sn.';'.$this->givenName."\n";
416
        $ret .= 'FN:'.$this->givenName."\n";
417
        $titles = $this->title;
418
        if($titles !== false)
419
        {
420
            $ret .= 'TITLE:'.implode(',', $titles)."\n";
421
        }
422
        $ret .= "ORG: Austin Artistic Reconstruction\n";
423
        $ret .= 'TEL;TYPE=MOBILE,VOICE:'.$this->mobile."\n";
424
        $ret .= 'EMAIL;TYPE=PREF,INTERNET:'.$this->mail."\n";
425
        $ret .= "END:VCARD\n";
426
        return $ret;
427
    }
428
}
429
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
430