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

src/User/UserService.php (1 issue)

Check for incompatible return types

Best Practice Bug Major

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) {
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;
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) {
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