This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 contains functionality to keep track of notifications for players and communicate with external push services |
||
4 | * |
||
5 | * @package BZiON\Models |
||
6 | * @license https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3 |
||
7 | */ |
||
8 | |||
9 | use BZIon\Event\Event; |
||
10 | use BZIon\Event\Events; |
||
11 | use BZIon\Model\Column\Timestamp; |
||
12 | use BZIon\NotificationAdapter\NotificationAdapter; |
||
13 | |||
14 | /** |
||
15 | * A notification to a player |
||
16 | * @package BZiON\Models |
||
17 | */ |
||
18 | class Notification extends Model |
||
19 | { |
||
20 | use Timestamp; |
||
21 | |||
22 | /** |
||
23 | * The id of the notified player |
||
24 | * @var int |
||
25 | */ |
||
26 | protected $receiver; |
||
27 | |||
28 | /** |
||
29 | * The type of the notification |
||
30 | * |
||
31 | * Can be one of the constants in BZIon\Event\Events |
||
32 | * |
||
33 | * @var int |
||
34 | */ |
||
35 | protected $type; |
||
36 | |||
37 | /** |
||
38 | * The event of the notification |
||
39 | * @var Event |
||
40 | */ |
||
41 | protected $event; |
||
42 | |||
43 | /** |
||
44 | * Services that will be notified when a new notification is created |
||
45 | * @var NotificationAdapter[] |
||
46 | */ |
||
47 | private static $adapters = array(); |
||
48 | |||
49 | const DEFAULT_STATUS = 'read'; |
||
50 | |||
51 | /** |
||
52 | * The name of the database table used for queries |
||
53 | */ |
||
54 | const TABLE = "notifications"; |
||
55 | |||
56 | /** |
||
57 | * {@inheritdoc} |
||
58 | */ |
||
59 | View Code Duplication | protected function assignResult($notification) |
|
0 ignored issues
–
show
|
|||
60 | { |
||
61 | $this->receiver = $notification['receiver']; |
||
62 | $this->type = $notification['type']; |
||
63 | $this->event = unserialize($notification['event']); |
||
64 | $this->status = $notification['status']; |
||
65 | $this->timestamp = TimeDate::fromMysql($notification['timestamp']); |
||
66 | } |
||
67 | |||
68 | 2 | /** |
|
69 | * Enter a new notification into the database |
||
70 | 2 | * @param int $receiver The receiver's ID |
|
71 | 2 | * @param string $type The type of the notification |
|
72 | 2 | * @param Event $event The event of the notification |
|
73 | 2 | * @param string $timestamp The timestamp of the notification |
|
74 | 2 | * @param string $status The status of the notification (unread, read, deleted) |
|
75 | 2 | * @return Notification An object representing the notification that was just entered |
|
76 | */ |
||
77 | View Code Duplication | public static function newNotification($receiver, $type, $event, $timestamp = "now", $status = "unread") |
|
0 ignored issues
–
show
This method seems to be duplicated in 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. ![]() |
|||
78 | { |
||
79 | $notification = self::create(array( |
||
80 | "receiver" => $receiver, |
||
81 | "type" => $type, |
||
82 | "event" => serialize($event), |
||
83 | "timestamp" => TimeDate::from($timestamp)->toMysql(), |
||
84 | "status" => $status |
||
85 | )); |
||
86 | 2 | ||
87 | return $notification; |
||
88 | 2 | } |
|
89 | 2 | ||
90 | 2 | /** |
|
91 | 2 | * Show a list of notifications for a specific user |
|
92 | 2 | * @param int $receiver The ID of the recipient of the notifications |
|
93 | 2 | * @param bool $onlyUnread False to show both unread & read notifications |
|
94 | * @return Notification[] |
||
95 | */ |
||
96 | 2 | public static function getNotifications($receiver, $onlyUnread = false) |
|
97 | { |
||
98 | $statuses = array('unread'); |
||
99 | if (!$onlyUnread) { |
||
100 | $statuses[] = 'read'; |
||
101 | } |
||
102 | |||
103 | return self::getQueryBuilder() |
||
104 | ->where('status')->isOneOf($statuses) |
||
105 | ->where('receiver')->is($receiver) |
||
106 | ->getModels(); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Show the number of notifications the user hasn't read yet |
||
111 | * @param int $receiver |
||
112 | * @return int |
||
113 | */ |
||
114 | public static function countUnreadNotifications($receiver) |
||
115 | { |
||
116 | return self::fetchCount("WHERE receiver = ? AND status = 'unread'", |
||
117 | $receiver |
||
0 ignored issues
–
show
$receiver is of type integer , but the function expects a array .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
118 | ); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Get the receiving player of the notification |
||
123 | 1 | * @return Player |
|
124 | */ |
||
125 | 1 | public function getReceiver() |
|
126 | 1 | { |
|
127 | return Player::get($this->receiver); |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * Get the type of the notification |
||
132 | * |
||
133 | * Do not use Notification::getType(), as it returns the name of the class |
||
134 | 2 | * (i.e. notification) |
|
135 | * |
||
136 | 2 | * @return int |
|
137 | */ |
||
138 | public function getCategory() |
||
139 | { |
||
140 | return $this->type; |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Get the event of the notification |
||
145 | * @return Event |
||
146 | 1 | */ |
|
147 | public function getEvent() |
||
148 | 1 | { |
|
149 | return $this->event; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Finds if the notification has been read by the user |
||
154 | * |
||
155 | 1 | * This returns true even if the notification is deleted |
|
156 | * @return bool |
||
157 | 1 | */ |
|
158 | public function isRead() |
||
159 | { |
||
160 | return $this->status != "unread"; |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Mark the notification as read by the user |
||
165 | * @return void |
||
166 | 1 | */ |
|
167 | public function markAsRead() |
||
168 | 1 | { |
|
169 | if ($this->status == "deleted") { |
||
170 | return; |
||
171 | } |
||
172 | |||
173 | $this->update('status', $this->status = "read"); |
||
174 | } |
||
175 | 1 | ||
176 | /** |
||
177 | 1 | * Make sure that the user is shown the notification immediately if they are |
|
178 | * browsing |
||
179 | */ |
||
180 | public function push() |
||
181 | 1 | { |
|
182 | 1 | self::pushEvent('notification', $this); |
|
183 | } |
||
184 | |||
185 | /** |
||
186 | * Get the available actions for the notification |
||
187 | * |
||
188 | 1 | * @param bool $email Whether actions should be formatted for e-mails |
|
189 | * @return array |
||
190 | 1 | */ |
|
191 | 1 | public function getActions($email = false) |
|
192 | { |
||
193 | switch ($this->type) { |
||
194 | case Events::TEAM_INVITE: |
||
195 | return array( |
||
196 | ($email) ? 'Accept invitation' : 'Accept' => $this->event->getInvitation()->getUrl('accept', $email) |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
BZIon\Event\Event as the method getInvitation() does only exist in the following sub-classes of BZIon\Event\Event : BZIon\Event\TeamInviteEvent . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
197 | ); |
||
198 | default: |
||
199 | return array(); |
||
200 | } |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Push an event to the event adapters |
||
205 | * @param string $type The type of the event |
||
206 | * @param mixed $data The data for the event |
||
207 | * @return void |
||
208 | */ |
||
209 | public static function pushEvent($type, $data = null) |
||
210 | { |
||
211 | switch ($type) { |
||
212 | case 'message': |
||
213 | $message = array( |
||
214 | 'conversation' => $data['message']->getConversation()->getId(), |
||
215 | 'message' => $data['message']->getId(), |
||
216 | 'author' => $data['message']->getAuthor()->getId(), |
||
217 | 1 | 'recipients' => $data['recipients'] |
|
218 | ); |
||
219 | break; |
||
220 | 1 | case 'notification': |
|
221 | $message = array( |
||
222 | 1 | 'type' => $data->getType(), |
|
223 | 1 | 'receiver' => $data->getReceiver()->getId(), |
|
224 | 1 | 'notification' => $data->getId() |
|
225 | 1 | ); |
|
226 | break; |
||
227 | 1 | case 'blank': |
|
228 | 1 | $message = null; |
|
229 | break; |
||
230 | 1 | default: |
|
231 | 1 | $message = $data; |
|
232 | 1 | } |
|
233 | |||
234 | 1 | foreach (self::$adapters as $adapter) { |
|
235 | $adapter->trigger($type, $message); |
||
236 | } |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Initialize the external push adapters |
||
241 | * @return void |
||
242 | 1 | */ |
|
243 | public static function initializeAdapters() |
||
244 | { |
||
245 | 1 | if (self::$adapters) { |
|
0 ignored issues
–
show
The expression
self::$adapters of type BZIon\NotificationAdapter\NotificationAdapter[] 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 ![]() |
|||
246 | // The adapters have already been initialized, no need to do anything! |
||
247 | return; |
||
248 | } |
||
249 | |||
250 | $adapters = array( |
||
251 | 1 | 'BZIon\NotificationAdapter\WebSocketAdapter' |
|
252 | ); |
||
253 | 1 | ||
254 | foreach ($adapters as $adapter) { |
||
255 | if ($adapter::isEnabled()) { |
||
256 | self::$adapters[] = new $adapter(); |
||
257 | } |
||
258 | } |
||
259 | 1 | } |
|
260 | |||
261 | /** |
||
262 | 1 | * {@inheritdoc} |
|
263 | 1 | */ |
|
264 | 1 | public static function getActiveStatuses() |
|
265 | { |
||
266 | return array('read', 'unread'); |
||
267 | 1 | } |
|
268 | |||
269 | /** |
||
270 | * Get a query builder for notifications |
||
271 | * @return NotificationQueryBuilder |
||
272 | */ |
||
273 | public static function getQueryBuilder() |
||
274 | { |
||
275 | return new NotificationQueryBuilder('Notification', array( |
||
276 | 'columns' => array( |
||
277 | 'receiver' => 'receiver', |
||
278 | 'timestamp' => 'timestamp', |
||
279 | 'status' => 'status' |
||
280 | ) |
||
281 | )); |
||
282 | } |
||
283 | } |
||
284 |
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.