Completed
Push — master ( 4925fd...b79622 )
by Peder
01:47
created

src/User/UserService.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Peto16\User;
4
5
class UserService
6
{
7
    private $userStorage;
8
    private $session;
9
10
11
12
    /**
13
     * Constructor for UserService
14
     * @param object            $di dependency injection.
15
     */
16 9
    public function __construct($di)
17
    {
18 9
        $this->userStorage = new UserStorage();
19 9
        $this->userStorage->setDb($di->get("db"));
20 9
        $this->session = $di->get("session");
21 9
    }
22
23
24
25
    /**
26
     * Create user.
27
     *
28
     * @param  object           $user User object to store.
29
     * @return void
30
     */
31 1
    public function createUser($user)
32
    {
33 1
        if ($this->userStorage->getUserByField("email", $user->email)) {
34 1
            throw new Exception("E-postadress används redan.");
35
        }
36 1
        if ($this->userStorage->getUserByField("username", $user->username)) {
37 1
            throw new Exception("Användarnamn redan taget.");
38
        }
39 1
        $this->userStorage->createUser($user);
40 1
    }
41
42
43
44
    /**
45
     * Update user.
46
     *
47
     * @param  object           $user User object to update.
48
     * @return void
49
     */
50 2
    public function updateUser($user)
51
    {
52 2
        $this->userStorage->updateUser($user);
53 2
    }
54
55
56
57
    /**
58
     * Delete user. Validates if user is admin to be able to delete
59
     *
60
     * @param  integer          $id user id.
61
     *
62
     * @return boolean
63
     */
64 2
    public function deleteUser($id)
65
    {
66 2
        if ($this->validLoggedInAdmin()) {
67 2
            return $this->userStorage->deleteUser($id);
68
        }
69 1
        return false;
70
    }
71
72
73
74
    /**
75
     * Dynamicly get user by propertie.
76
     *
77
     * @param string            $field field to search by.
78
     *
79
     * @param array             $data to search for.
80
     *
81
     * @return User
82
     *
83
     */
84 10
    public function getUserByField($field, $data)
85
    {
86 10
        $user = new User();
87 10
        $userVarArray = get_object_vars($user);
88 10
        $arrayKeys = array_keys($userVarArray);
89 10
        $userData = $this->userStorage->getUserByField($field, $data);
90 10
        if (!$userData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91 2
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Peto16\User\UserService::getUserByField of type Peto16\User\User.

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...
92
        }
93 9
        foreach ($arrayKeys as $key) {
94 9
            $user->{$key} = $userData->$key;
95 9
        }
96 9
        return $user;
97
    }
98
99
100
101
    /**
102
     * Find all users stored.
103
     *
104
     * @return array                Of users
105
     */
106 2
    public function findAllUsers()
107
    {
108 2
        return $this->userStorage->findAllUsers();
109
    }
110
111
112
113
    /**
114
     * Check if user is logged in.
115
     *
116
     * @return boolean
117
     */
118 2
    public function checkLoggedin()
119
    {
120 2
        return $this->session->has("user");
121
    }
122
123
124
125
    /**
126
     * Login user and redirect to admin.
127
     *
128
     * @return boolean
129
     */
130 2
    public function login($username, $password)
131
    {
132 2
        $user = $this->getUserByField("username", $username);
133
134 2
        if ($password === null) {
135 2
            throw new Exception("Empty password field.");
136
        }
137
138 1
        if (empty($user)) {
139 1
            throw new Exception("Error, not valid credentials.");
140
        }
141
142 1
        if ((int)$user->enabled === 0) {
143 1
            throw new Exception("Error, disabled account.");
144
        }
145
146 1
        if ($this->validatePassword($password, $user->password)) {
147 1
            $this->session->set("user", $user);
148 1
            return true;
149
        }
150 1
        throw new Exception("Error, not valid credentials.");
151
        return false;
0 ignored issues
show
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
152
    }
153
154
155
156
    /**
157
     * Check if a user is logged in and returns that user
158
     *
159
     * @return obj          user or null
160
     */
161 6
    public function getCurrentLoggedInUser()
162
    {
163 6
        return $this->session->get("user");
164
    }
165
166
167
168
    /**
169
     * Validate pasword
170
     *
171
     * @method              password_verify Method to verify password
172
     *
173
     * @param  string       $password Password to be validated.
174
     *
175
     * @return boolean      Return true if valid else false.
176
     */
177 1
    private function validatePassword($password, $dbpassword)
178
    {
179 1
        return password_verify($password, $dbpassword);
180
    }
181
182
183
184
    /**
185
     * Check if logged in user is valid and admin.
186
     *
187
     * @return boolean              Returns true or false if user is valid administrator.
188
     */
189 2
    public function validLoggedInAdmin()
190
    {
191 2
        $loggedInUser = $this->getCurrentLoggedInUser();
192
        if ($loggedInUser
193 2
            && $loggedInUser->administrator
194 2
            && $loggedInUser->deleted === null
195 2
            && $loggedInUser->enabled) {
196 2
                return true;
197
        }
198 1
        return false;
199
    }
200
201
202
203
    /**
204
     * Generate gravatar from email or return default avatar.
205
     *
206
     * @param  string           $email email adress
207
     * @return string           Gravatar url.
208
     */
209 1
    public function generateGravatarUrl($email = null)
210
    {
211 1
        if ($email) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $email of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
212 1
            return "https://s.gravatar.com/avatar/" . md5(strtolower(trim($email)));
213
        }
214 1
        return "http://www.gravatar.com/avatar/?d=identicon";
215
    }
216
}
217