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 |
||
0 ignored issues
–
show
|
|||
2 | /** |
||
3 | * @package Freemius |
||
4 | * @copyright Copyright (c) 2015, Freemius, Inc. |
||
5 | * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3 |
||
6 | * @since 1.0.7 |
||
7 | */ |
||
8 | |||
9 | if ( ! defined( 'ABSPATH' ) ) { |
||
10 | exit; |
||
11 | } |
||
12 | |||
13 | class FS_Admin_Notice_Manager { |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
14 | /** |
||
15 | * @since 1.2.2 |
||
16 | * |
||
17 | * @var string |
||
18 | */ |
||
19 | protected $_module_unique_affix; |
||
20 | /** |
||
21 | * @var string |
||
22 | */ |
||
23 | protected $_id; |
||
24 | /** |
||
25 | * @var string |
||
26 | */ |
||
27 | protected $_title; |
||
28 | /** |
||
29 | * @var array[string]array |
||
30 | */ |
||
31 | private $_notices = array(); |
||
32 | /** |
||
33 | * @var FS_Key_Value_Storage |
||
34 | */ |
||
35 | private $_sticky_storage; |
||
36 | /** |
||
37 | * @var FS_Logger |
||
38 | */ |
||
39 | protected $_logger; |
||
40 | /** |
||
41 | * @since 2.0.0 |
||
42 | * @var int The ID of the blog that is associated with the current site level admin notices. |
||
43 | */ |
||
44 | private $_blog_id = 0; |
||
45 | /** |
||
46 | * @since 2.0.0 |
||
47 | * @var bool |
||
48 | */ |
||
49 | private $_is_network_notices; |
||
50 | |||
51 | /** |
||
52 | * @var FS_Admin_Notice_Manager[] |
||
53 | */ |
||
54 | private static $_instances = array(); |
||
55 | |||
56 | /** |
||
57 | * @param string $id |
||
58 | * @param string $title |
||
59 | * @param string $module_unique_affix |
||
60 | * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on |
||
61 | * network and blog admin pages. |
||
62 | * @param bool $network_level_or_blog_id Since 2.0.0 |
||
63 | * |
||
64 | * @return \FS_Admin_Notice_Manager |
||
65 | */ |
||
66 | static function instance( |
||
0 ignored issues
–
show
|
|||
67 | $id, |
||
68 | $title = '', |
||
69 | $module_unique_affix = '', |
||
70 | $is_network_and_blog_admins = false, |
||
71 | $network_level_or_blog_id = false |
||
72 | ) { |
||
73 | if ( $is_network_and_blog_admins ) { |
||
74 | $network_level_or_blog_id = true; |
||
75 | } |
||
76 | |||
77 | $key = strtolower( $id ); |
||
78 | |||
79 | if ( is_multisite() ) { |
||
80 | if ( true === $network_level_or_blog_id ) { |
||
81 | $key .= ':ms'; |
||
82 | } else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) { |
||
83 | $key .= ":{$network_level_or_blog_id}"; |
||
84 | } else { |
||
85 | $network_level_or_blog_id = get_current_blog_id(); |
||
86 | |||
87 | $key .= ":{$network_level_or_blog_id}"; |
||
88 | } |
||
89 | } |
||
90 | |||
91 | if ( ! isset( self::$_instances[ $key ] ) ) { |
||
92 | self::$_instances[ $key ] = new FS_Admin_Notice_Manager( |
||
93 | $id, |
||
94 | $title, |
||
95 | $module_unique_affix, |
||
96 | $is_network_and_blog_admins, |
||
97 | $network_level_or_blog_id |
||
98 | ); |
||
99 | } |
||
100 | |||
101 | return self::$_instances[ $key ]; |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * @param string $id |
||
106 | * @param string $title |
||
107 | * @param string $module_unique_affix |
||
108 | * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and |
||
109 | * blog admin pages. |
||
110 | * @param bool|int $network_level_or_blog_id |
||
111 | */ |
||
112 | protected function __construct( |
||
113 | $id, |
||
114 | $title = '', |
||
115 | $module_unique_affix = '', |
||
116 | $is_network_and_blog_admins = false, |
||
117 | $network_level_or_blog_id = false |
||
118 | ) { |
||
119 | $this->_id = $id; |
||
120 | $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->_id . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); |
||
121 | $this->_title = ! empty( $title ) ? $title : ''; |
||
122 | $this->_module_unique_affix = $module_unique_affix; |
||
123 | $this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_id, $network_level_or_blog_id ); |
||
0 ignored issues
–
show
It seems like
$network_level_or_blog_id defined by parameter $network_level_or_blog_id on line 117 can also be of type integer ; however, FS_Key_Value_Storage::instance() does only seem to accept boolean , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
124 | |||
125 | if ( is_multisite() ) { |
||
126 | $this->_is_network_notices = ( true === $network_level_or_blog_id ); |
||
127 | |||
128 | if ( is_numeric( $network_level_or_blog_id ) ) { |
||
129 | $this->_blog_id = $network_level_or_blog_id; |
||
0 ignored issues
–
show
It seems like
$network_level_or_blog_id can also be of type double or string . However, the property $_blog_id is declared as type integer . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
130 | } |
||
131 | } else { |
||
132 | $this->_is_network_notices = false; |
||
133 | } |
||
134 | |||
135 | $is_network_admin = fs_is_network_admin(); |
||
136 | $is_blog_admin = fs_is_blog_admin(); |
||
137 | |||
138 | if ( ( $this->_is_network_notices && $is_network_admin ) || |
||
139 | ( ! $this->_is_network_notices && $is_blog_admin ) || |
||
140 | ( $is_network_and_blog_admins && ( $is_network_admin || $is_blog_admin ) ) |
||
141 | ) { |
||
142 | if ( 0 < count( $this->_sticky_storage ) ) { |
||
143 | $ajax_action_suffix = str_replace( ':', '-', $this->_id ); |
||
144 | |||
145 | // If there are sticky notices for the current slug, add a callback |
||
146 | // to the AJAX action that handles message dismiss. |
||
147 | add_action( "wp_ajax_fs_dismiss_notice_action_{$ajax_action_suffix}", array( |
||
148 | &$this, |
||
149 | 'dismiss_notice_ajax_callback' |
||
150 | ) ); |
||
151 | |||
152 | foreach ( $this->_sticky_storage as $msg ) { |
||
153 | // Add admin notice. |
||
154 | $this->add( |
||
155 | $msg['message'], |
||
156 | $msg['title'], |
||
157 | $msg['type'], |
||
158 | true, |
||
159 | $msg['id'], |
||
160 | false, |
||
161 | isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null, |
||
162 | ! empty( $msg['plugin'] ) ? $msg['plugin'] : null, |
||
163 | $is_network_and_blog_admins |
||
164 | ); |
||
165 | } |
||
166 | } |
||
167 | } |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Remove sticky message by ID. |
||
172 | * |
||
173 | * @author Vova Feldman (@svovaf) |
||
174 | * @since 1.0.7 |
||
175 | * |
||
176 | */ |
||
177 | function dismiss_notice_ajax_callback() { |
||
0 ignored issues
–
show
|
|||
178 | $this->_sticky_storage->remove( $_POST['message_id'] ); |
||
179 | wp_die(); |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Rendered sticky message dismiss JavaScript. |
||
184 | * |
||
185 | * @author Vova Feldman (@svovaf) |
||
186 | * @since 1.0.7 |
||
187 | */ |
||
188 | static function _add_sticky_dismiss_javascript() { |
||
0 ignored issues
–
show
|
|||
189 | $params = array(); |
||
190 | fs_require_once_template( 'sticky-admin-notice-js.php', $params ); |
||
191 | } |
||
192 | |||
193 | private static $_added_sticky_javascript = false; |
||
194 | |||
195 | /** |
||
196 | * Hook to the admin_footer to add sticky message dismiss JavaScript handler. |
||
197 | * |
||
198 | * @author Vova Feldman (@svovaf) |
||
199 | * @since 1.0.7 |
||
200 | */ |
||
201 | private static function has_sticky_messages() { |
||
202 | if ( ! self::$_added_sticky_javascript ) { |
||
203 | add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) ); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * Handle admin_notices by printing the admin messages stacked in the queue. |
||
209 | * |
||
210 | * @author Vova Feldman (@svovaf) |
||
211 | * @since 1.0.4 |
||
212 | * |
||
213 | */ |
||
214 | function _admin_notices_hook() { |
||
0 ignored issues
–
show
|
|||
215 | if ( function_exists( 'current_user_can' ) && |
||
216 | ! current_user_can( 'manage_options' ) |
||
217 | ) { |
||
218 | // Only show messages to admins. |
||
219 | return; |
||
220 | } |
||
221 | |||
222 | |||
223 | $show_admin_notices = ( ! $this->is_gutenberg_page() ); |
||
224 | |||
225 | foreach ( $this->_notices as $id => $msg ) { |
||
226 | if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) { |
||
227 | if ( get_current_user_id() != $msg['wp_user_id'] ) { |
||
228 | continue; |
||
229 | } |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Added a filter to control the visibility of admin notices. |
||
234 | * |
||
235 | * Usage example: |
||
236 | * |
||
237 | * /** |
||
238 | * * @param bool $show |
||
239 | * * @param array $msg { |
||
240 | * * @var string $message The actual message. |
||
241 | * * @var string $title An optional message title. |
||
242 | * * @var string $type The type of the message ('success', 'update', 'warning', 'promotion'). |
||
243 | * * @var string $id The unique identifier of the message. |
||
244 | * * @var string $manager_id The unique identifier of the notices manager. For plugins it would be the plugin's slug, for themes - `<slug>-theme`. |
||
245 | * * @var string $plugin The product's title. |
||
246 | * * @var string $wp_user_id An optional WP user ID that this admin notice is for. |
||
247 | * * } |
||
248 | * * |
||
249 | * * @return bool |
||
250 | * *\/ |
||
251 | * function my_custom_show_admin_notice( $show, $msg ) { |
||
252 | * if ('trial_promotion' != $msg['id']) { |
||
253 | * return false; |
||
254 | * } |
||
255 | * |
||
256 | * return $show; |
||
257 | * } |
||
258 | * |
||
259 | * my_fs()->add_filter( 'show_admin_notice', 'my_custom_show_admin_notice', 10, 2 ); |
||
260 | * |
||
261 | * @author Vova Feldman |
||
262 | * @since 2.2.0 |
||
263 | */ |
||
264 | $show_notice = call_user_func_array( 'fs_apply_filter', array( |
||
265 | $this->_module_unique_affix, |
||
266 | 'show_admin_notice', |
||
267 | $show_admin_notices, |
||
268 | $msg |
||
269 | ) ); |
||
270 | |||
271 | if ( true !== $show_notice ) { |
||
272 | continue; |
||
273 | } |
||
274 | |||
275 | fs_require_template( 'admin-notice.php', $msg ); |
||
276 | |||
277 | if ( $msg['sticky'] ) { |
||
278 | self::has_sticky_messages(); |
||
279 | } |
||
280 | } |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * Enqueue common stylesheet to style admin notice. |
||
285 | * |
||
286 | * @author Vova Feldman (@svovaf) |
||
287 | * @since 1.0.7 |
||
288 | */ |
||
289 | function _enqueue_styles() { |
||
0 ignored issues
–
show
|
|||
290 | fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * Check if the current page is the Gutenberg block editor. |
||
295 | * |
||
296 | * @author Vova Feldman (@svovaf) |
||
297 | * @since 2.2.3 |
||
298 | * |
||
299 | * @return bool |
||
300 | */ |
||
301 | function is_gutenberg_page() { |
||
0 ignored issues
–
show
|
|||
302 | if ( function_exists( 'is_gutenberg_page' ) && |
||
303 | is_gutenberg_page() |
||
304 | ) { |
||
305 | // The Gutenberg plugin is on. |
||
306 | return true; |
||
307 | } |
||
308 | |||
309 | $current_screen = get_current_screen(); |
||
310 | |||
311 | if ( method_exists( $current_screen, 'is_block_editor' ) && |
||
312 | $current_screen->is_block_editor() |
||
313 | ) { |
||
314 | // Gutenberg page on 5+. |
||
315 | return true; |
||
316 | } |
||
317 | |||
318 | return false; |
||
319 | } |
||
320 | |||
321 | /** |
||
322 | * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked. |
||
323 | * |
||
324 | * @author Vova Feldman (@svovaf) |
||
325 | * @since 1.0.4 |
||
326 | * |
||
327 | * @param string $message |
||
328 | * @param string $title |
||
329 | * @param string $type |
||
330 | * @param bool $is_sticky |
||
331 | * @param string $id Message ID |
||
332 | * @param bool $store_if_sticky |
||
333 | * @param number|null $wp_user_id |
||
334 | * @param string|null $plugin_title |
||
335 | * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network |
||
336 | * and blog admin pages. |
||
337 | * |
||
338 | * @uses add_action() |
||
339 | */ |
||
340 | function add( |
||
0 ignored issues
–
show
|
|||
341 | $message, |
||
342 | $title = '', |
||
343 | $type = 'success', |
||
344 | $is_sticky = false, |
||
345 | $id = '', |
||
346 | $store_if_sticky = true, |
||
347 | $wp_user_id = null, |
||
348 | $plugin_title = null, |
||
349 | $is_network_and_blog_admins = false |
||
350 | ) { |
||
351 | $notices_type = $this->get_notices_type(); |
||
352 | |||
353 | if ( empty( $this->_notices ) ) { |
||
354 | if ( ! $is_network_and_blog_admins ) { |
||
355 | add_action( $notices_type, array( &$this, "_admin_notices_hook" ) ); |
||
356 | } else { |
||
357 | add_action( 'network_admin_notices', array( &$this, "_admin_notices_hook" ) ); |
||
358 | add_action( 'admin_notices', array( &$this, "_admin_notices_hook" ) ); |
||
359 | } |
||
360 | |||
361 | add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) ); |
||
362 | } |
||
363 | |||
364 | if ( '' === $id ) { |
||
365 | $id = md5( $title . ' ' . $message . ' ' . $type ); |
||
366 | } |
||
367 | |||
368 | $message_object = array( |
||
369 | 'message' => $message, |
||
370 | 'title' => $title, |
||
371 | 'type' => $type, |
||
372 | 'sticky' => $is_sticky, |
||
373 | 'id' => $id, |
||
374 | 'manager_id' => $this->_id, |
||
375 | 'plugin' => ( ! is_null( $plugin_title ) ? $plugin_title : $this->_title ), |
||
376 | 'wp_user_id' => $wp_user_id, |
||
377 | ); |
||
378 | |||
379 | if ( $is_sticky && $store_if_sticky ) { |
||
380 | $this->_sticky_storage->{$id} = $message_object; |
||
381 | } |
||
382 | |||
383 | $this->_notices[ $id ] = $message_object; |
||
384 | } |
||
385 | |||
386 | /** |
||
387 | * @author Vova Feldman (@svovaf) |
||
388 | * @since 1.0.7 |
||
389 | * |
||
390 | * @param string|string[] $ids |
||
391 | */ |
||
392 | function remove_sticky( $ids ) { |
||
0 ignored issues
–
show
|
|||
393 | if ( ! is_array( $ids ) ) { |
||
394 | $ids = array( $ids ); |
||
395 | } |
||
396 | |||
397 | foreach ( $ids as $id ) { |
||
398 | // Remove from sticky storage. |
||
399 | $this->_sticky_storage->remove( $id ); |
||
400 | |||
401 | if ( isset( $this->_notices[ $id ] ) ) { |
||
402 | unset( $this->_notices[ $id ] ); |
||
403 | } |
||
404 | } |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * Check if sticky message exists by id. |
||
409 | * |
||
410 | * @author Vova Feldman (@svovaf) |
||
411 | * @since 1.0.9 |
||
412 | * |
||
413 | * @param $id |
||
414 | * |
||
415 | * @return bool |
||
416 | */ |
||
417 | function has_sticky( $id ) { |
||
0 ignored issues
–
show
|
|||
418 | return isset( $this->_sticky_storage[ $id ] ); |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Adds sticky admin notification. |
||
423 | * |
||
424 | * @author Vova Feldman (@svovaf) |
||
425 | * @since 1.0.7 |
||
426 | * |
||
427 | * @param string $message |
||
428 | * @param string $id Message ID |
||
429 | * @param string $title |
||
430 | * @param string $type |
||
431 | * @param number|null $wp_user_id |
||
432 | * @param string|null $plugin_title |
||
433 | * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network |
||
434 | * and blog admin pages. |
||
435 | */ |
||
436 | function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false ) { |
||
0 ignored issues
–
show
|
|||
437 | if ( ! empty( $this->_module_unique_affix ) ) { |
||
438 | $message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message ); |
||
439 | $title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title ); |
||
440 | } |
||
441 | |||
442 | $this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins ); |
||
443 | } |
||
444 | |||
445 | /** |
||
446 | * Clear all sticky messages. |
||
447 | * |
||
448 | * @author Vova Feldman (@svovaf) |
||
449 | * @since 1.0.8 |
||
450 | */ |
||
451 | function clear_all_sticky() { |
||
0 ignored issues
–
show
|
|||
452 | $this->_sticky_storage->clear_all(); |
||
453 | } |
||
454 | |||
455 | #-------------------------------------------------------------------------------- |
||
456 | #region Helper Method |
||
457 | #-------------------------------------------------------------------------------- |
||
458 | |||
459 | /** |
||
460 | * @author Vova Feldman (@svovaf) |
||
461 | * @since 2.0.0 |
||
462 | * |
||
463 | * @return string |
||
464 | */ |
||
465 | private function get_notices_type() { |
||
466 | return $this->_is_network_notices ? |
||
467 | 'network_admin_notices' : |
||
468 | 'admin_notices'; |
||
469 | } |
||
470 | |||
471 | #endregion |
||
472 | } |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.