Issues (41)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Friends/Traits/Friendable.php (20 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
 * This file is part of Friends.
4
 *
5
 * (c) Christopher Lass <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Arubacao\Friends\Traits;
12
13
use Arubacao\Friends\FriendshipStatus;
14
use Illuminate\Support\Facades\Config;
15
16
trait Friendable
17
{
18
    /**
19
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
20
     */
21 22
    public function friends_i_am_sender()
22
    {
23 22
        return $this->belongsToMany(
0 ignored issues
show
It seems like belongsToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
24 22
            Config::get('friends.user_model'),
25 22
            'friends',
26 22
            'sender_id', 'recipient_id')
27 22
            ->withTimestamps()
28 22
            ->withPivot([
29 22
                'friendship_status',
30 22
            ])
31 22
            ->orderBy('friends.updated_at', 'desc');
32
    }
33
34
    /**
35
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
36
     */
37 22
    public function friends_i_am_recipient()
38
    {
39 22
        return $this->belongsToMany(
0 ignored issues
show
It seems like belongsToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
40 22
            Config::get('friends.user_model'),
41 22
            'friends',
42 22
            'recipient_id', 'sender_id')
43 22
            ->withTimestamps()
44 22
            ->withPivot([
45 22
                'friendship_status',
46 22
            ])
47 22
            ->orderBy('friends.updated_at', 'desc');
48
    }
49
50
    /**
51
     * @return \Illuminate\Database\Eloquent\Builder
52
     */
53 1
    public function scopeIncludeRelationshipsWith($query, $user)
54
    {
55 1
        $userId = $this->retrieveUserId($user);
56
57 1
        return $query->with([
58
            'friends_i_am_sender' => function ($queryIn) use ($userId) {
59 1
                $queryIn->where('friends.recipient_id', $userId)
60 1
                    ->get();
61 1
            },
62
            'friends_i_am_recipient' => function ($queryIn) use ($userId) {
63 1
                $queryIn->where('friends.sender_id', $userId)
64 1
                    ->get();
65 1
            },
66 1
        ]);
67
    }
68
69
    /**
70
     * @return \Illuminate\Database\Eloquent\Collection
71
     */
72 10
    public function friends()
73
    {
74 10
        $me = $this->with([
0 ignored issues
show
It seems like with() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $me. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
75
            'friends_i_am_sender' => function ($query) {
76 10
                $query->where('friends.friendship_status', FriendshipStatus::ACCEPTED)
77 10
                    ->get();
78 10
            },
79
            'friends_i_am_recipient' => function ($query) {
80 10
                $query->where('friends.friendship_status', FriendshipStatus::ACCEPTED)
81 10
                    ->get();
82 10
            },
83 10
        ])
84 10
            ->where('id', '=', $this->getKey())
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
85 10
            ->first();
86
87 10
        $friends = $this->mergedFriends($me);
88
89 10
        return $friends;
90
    }
91
92
    /**
93
     * @return \Illuminate\Database\Eloquent\Collection
94
     */
95 2
    public function incoming_friends()
96
    {
97 2
        $me = $this->with([
0 ignored issues
show
It seems like with() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $me. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
98 2
            'friends_i_am_recipient' => function ($query) {
99 2
                $query->where('friends.friendship_status', FriendshipStatus::PENDING)
100 2
                    ->get();
101 2
            },
102 2
        ])
103 2
            ->where('id', '=', $this->getKey())
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
104 2
            ->first();
105
106 2
        return $me->friends_i_am_recipient;
107
    }
108
109
    /**
110
     * @return \Illuminate\Database\Eloquent\Collection
111
     */
112 11
    public function any_friends()
113
    {
114 11
        $me = $this->with([
0 ignored issues
show
It seems like with() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $me. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
115 11
            'friends_i_am_sender',
116 11
            'friends_i_am_recipient',
117 11
        ])
118 11
            ->where('id', '=', $this->getKey())
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
119 11
            ->first();
120
121 11
        $any_friends = $this->mergedFriends($me);
122
123 11
        return $any_friends;
124
    }
125
126
    /**
127
     * Alias to eloquent many-to-many relation's attach() method.
128
     *
129
     * @param int|User $user
130
     * @return bool
131
     */
132 21
    public function sendFriendRequestTo($user)
133
    {
134 21
        $userId = $this->retrieveUserId($user);
135
136 21
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
137
            // Method not allowed on self
138 1
            return false;
139
        }
140
141 20
        $relationship = $this->getRelationshipWith($userId, [
142 20
            FriendshipStatus::PENDING,
143 20
            FriendshipStatus::ACCEPTED,
144 20
        ]);
145
146 20
        if (! is_null($relationship)) {
147 5
            if ($relationship->pivot->friendship_status == FriendshipStatus::ACCEPTED) {
148
                // Already friends
149 2
                return false;
150
            }
151 3
            if ($relationship->pivot->friendship_status == FriendshipStatus::PENDING &&
152 3
                $relationship->pivot->recipient_id == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
153
                // Recipient already sent a friend request
154
                // Accept pending friend request
155 2
                $relationship->pivot->friendship_status = FriendshipStatus::ACCEPTED;
156 2
                $relationship->pivot->save();
157
                /* @todo: fire event friend request accepted */
158 2
                $this->reload();
159
160 2
                return true;
161
            }
162
163 1
            return false;
164
        }
165
166 20
        $this->friends_i_am_sender()->attach($userId, [
167 20
            'friendship_status' => FriendshipStatus::PENDING,
168 20
        ]);
169
        /* @todo: fire event friend request sent */
170
171 20
        $this->reload();
172
173 20
        return true;
174
    }
175
176
    /**
177
     * @param int|User $user
178
     * @return bool
179
     */
180 13
    public function acceptFriendRequestFrom($user)
181
    {
182 13
        $userId = $this->retrieveUserId($user);
183
184 13
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
185
            // Method not allowed on self
186
            return false;
187
        }
188
189 13
        $relationship = $this->getPendingRequestFrom($userId);
190
191 13
        if (! is_null($relationship)) {
192 12
            $relationship->pivot->friendship_status = FriendshipStatus::ACCEPTED;
193 12
            $relationship->pivot->save();
194
            /* @todo: fire event friend request accepted */
195 12
            $this->reload();
196
197 12
            return true;
198
        }
199
200 1
        return false;
201
    }
202
203
    /**
204
     * @param int|User $user
205
     * @return bool
206
     */
207 2
    public function denyFriendRequestFrom($user)
208
    {
209 2
        $userId = $this->retrieveUserId($user);
210
211 2
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
212
            // Method not allowed on self
213
            return false;
214
        }
215
216 2
        $relationship = $this->getPendingRequestFrom($userId);
217
218 2
        if (! is_null($relationship)) {
219 2
            $relationship->pivot->delete();
220
            /* @todo: fire event friend request denied */
221 2
            $this->reload();
222
223 2
            return true;
224
        }
225
226
        return false;
227
    }
228
229
    /**
230
     * @param int|User $user
231
     * @return bool
232
     */
233 1
    public function deleteFriend($user)
234
    {
235 1
        $userId = $this->retrieveUserId($user);
236
237 1
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
238
            // Method not allowed on self
239
            return false;
240
        }
241
242 1
        while ($relationship = $this->getRelationshipWith($userId, [
243 1
            FriendshipStatus::ACCEPTED,
244 1
            FriendshipStatus::PENDING,
245 1
        ])) {
246 1
            $relationship->pivot->delete();
247
            /* @todo: fire event friend deleted */
248 1
        }
249 1
        $this->reload();
250
251 1
        return true;
252
    }
253
254
    /**
255
     * @param int|array|User $user
256
     * @return bool
257
     */
258 2
    public function isFriendWith($user)
259
    {
260 2
        $userId = $this->retrieveUserId($user);
261
262 2
        return $this->hasRelationshipWith($userId, [FriendshipStatus::ACCEPTED]);
263
    }
264
265
    /**
266
     * @param int|array|User $user
267
     * @param array $status
268
     * @return bool
269
     */
270 2
    public function hasRelationshipWith($user, $status)
271
    {
272 2
        $userId = $this->retrieveUserId($user);
273
274 2
        $relationship = $this->getRelationshipWith($userId, $status);
275
276 2
        return (is_null($relationship)) ? false : true;
277
    }
278
279
    /**
280
     * @param int|array|User $user
281
     * @param array $status
282
     * @return mixed
283
     */
284 20
    public function getRelationshipWith($user, $status)
285
    {
286 20
        $userId = $this->retrieveUserId($user);
287
288 20
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
289
            // Method not allowed on self
290
            return;
291
        }
292
293 20
        $attempt1 = $this->friends_i_am_recipient()
294 20
            ->wherePivotIn('friendship_status', $status)
295 20
            ->wherePivot('sender_id', $userId)
296 20
            ->first();
297
298 20
        if (! is_null($attempt1)) {
299 3
            return $attempt1;
300
        }
301
302 20
        $attempt2 = $this->friends_i_am_sender()
303 20
            ->wherePivotIn('friendship_status', $status)
304 20
            ->wherePivot('recipient_id', $userId)
305 20
            ->first();
306
307 20
        if (! is_null($attempt2)) {
308 4
            return $attempt2;
309
        }
310 20
    }
311
312
    /**
313
     * @param int|array|User $user
314
     * @return bool
315
     */
316 4
    public function hasPendingRequestFrom($user)
317
    {
318 4
        $userId = $this->retrieveUserId($user);
319
320 4
        if ($userId == $this->getKey()) {
0 ignored issues
show
It seems like getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
321
            // Method not allowed on self
322
            return false;
323
        }
324
325 4
        $relationship = $this->getPendingRequestFrom($userId);
326
327 4
        if (! is_null($relationship)) {
328 2
            return true;
329
        }
330
331 4
        return false;
332
    }
333
334
    /**
335
     * @param int|array|User $user
336
     * @return int|null
337
     */
338 25
    private function retrieveUserId($user)
339
    {
340 25
        if (is_object($user)) {
341 23
            return $user->getKey();
342
        }
343 22
        if (is_array($user) && isset($user['id'])) {
344 1
            return $user['id'];
345
        }
346
347 21
        return $user;
348
    }
349
350
    /**
351
     * @param int $userId
352
     * @return mixed
353
     */
354 16
    private function getPendingRequestFrom($userId)
355
    {
356 16
        return $this->friends_i_am_recipient()
357 16
            ->wherePivot('friendship_status', FriendshipStatus::PENDING)
358 16
            ->wherePivot('sender_id', $userId)
359 16
            ->first();
360
    }
361
362
    /**
363
     * Eager load relations on the model.
364
     */
365 20
    private function reload()
366
    {
367 20
        $this->load('friends_i_am_recipient', 'friends_i_am_sender');
0 ignored issues
show
It seems like load() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
368 20
    }
369
370
    /**
371
     * @param User $me
372
     * @return \Illuminate\Database\Eloquent\Collection
373
     */
374 18
    private function mergedFriends($me)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $me. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
375
    {
376 18
        $friends = collect([]);
377 18
        $friends->push($me->friends_i_am_sender);
378 18
        $friends->push($me->friends_i_am_recipient);
379 18
        $friends = $friends->flatten();
380
381 18
        return $friends;
382
    }
383
}
384