Issues (2010)

Security Analysis    not enabled

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.

wp-includes/class-wp-widget.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
 * Widget API: WP_Widget base class
4
 *
5
 * @package WordPress
6
 * @subpackage Widgets
7
 * @since 4.4.0
8
 */
9
10
/**
11
 * Core base class extended to register widgets.
12
 *
13
 * This class must be extended for each widget, and WP_Widget::widget() must be overriden.
14
 *
15
 * If adding widget options, WP_Widget::update() and WP_Widget::form() should also be overridden.
16
 *
17
 * @since 2.8.0
18
 * @since 4.4.0 Moved to its own file from wp-includes/widgets.php
19
 */
20
class WP_Widget {
21
22
	/**
23
	 * Root ID for all widgets of this type.
24
	 *
25
	 * @since 2.8.0
26
	 * @access public
27
	 * @var mixed|string
28
	 */
29
	public $id_base;
30
31
	/**
32
	 * Name for this widget type.
33
	 *
34
	 * @since 2.8.0
35
	 * @access public
36
	 * @var string
37
	 */
38
	public $name;
39
40
	/**
41
	 * Option name for this widget type.
42
	 *
43
	 * @since 2.8.0
44
	 * @access public
45
	 * @var string
46
	 */
47
	public $option_name;
48
49
	/**
50
	 * Alt option name for this widget type.
51
	 *
52
	 * @since 2.8.0
53
	 * @access public
54
	 * @var string
55
	 */
56
	public $alt_option_name;
57
58
	/**
59
	 * Option array passed to wp_register_sidebar_widget().
60
	 *
61
	 * @since 2.8.0
62
	 * @access public
63
	 * @var array
64
	 */
65
	public $widget_options;
66
67
	/**
68
	 * Option array passed to wp_register_widget_control().
69
	 *
70
	 * @since 2.8.0
71
	 * @access public
72
	 * @var array
73
	 */
74
	public $control_options;
75
76
	/**
77
	 * Unique ID number of the current instance.
78
	 *
79
	 * @since 2.8.0
80
	 * @access public
81
	 * @var bool|int
82
	 */
83
	public $number = false;
84
85
	/**
86
	 * Unique ID string of the current instance (id_base-number).
87
	 *
88
	 * @since 2.8.0
89
	 * @access public
90
	 * @var bool|string
91
	 */
92
	public $id = false;
93
94
	/**
95
	 * Whether the widget data has been updated.
96
	 *
97
	 * Set to true when the data is updated after a POST submit - ensures it does
98
	 * not happen twice.
99
	 *
100
	 * @since 2.8.0
101
	 * @access public
102
	 * @var bool
103
	 */
104
	public $updated = false;
105
106
	//
107
	// Member functions that must be overriden by subclasses.
108
	//
109
110
	/**
111
	 * Echoes the widget content.
112
	 *
113
	 * Sub-classes should over-ride this function to generate their widget code.
114
	 *
115
	 * @since 2.8.0
116
	 * @access public
117
	 *
118
	 * @param array $args     Display arguments including 'before_title', 'after_title',
119
	 *                        'before_widget', and 'after_widget'.
120
	 * @param array $instance The settings for the particular instance of the widget.
121
	 */
122
	public function widget( $args, $instance ) {
123
		die('function WP_Widget::widget() must be over-ridden in a sub-class.');
124
	}
125
126
	/**
127
	 * Updates a particular instance of a widget.
128
	 *
129
	 * This function should check that `$new_instance` is set correctly. The newly-calculated
130
	 * value of `$instance` should be returned. If false is returned, the instance won't be
131
	 * saved/updated.
132
	 *
133
	 * @since 2.8.0
134
	 * @access public
135
	 *
136
	 * @param array $new_instance New settings for this instance as input by the user via
137
	 *                            WP_Widget::form().
138
	 * @param array $old_instance Old settings for this instance.
139
	 * @return array Settings to save or bool false to cancel saving.
140
	 */
141
	public function update( $new_instance, $old_instance ) {
142
		return $new_instance;
143
	}
144
145
	/**
146
	 * Outputs the settings update form.
147
	 *
148
	 * @since 2.8.0
149
	 * @access public
150
	 *
151
	 * @param array $instance Current settings.
152
	 * @return string Default return is 'noform'.
153
	 */
154
	public function form( $instance ) {
155
		echo '<p class="no-options-widget">' . __('There are no options for this widget.') . '</p>';
156
		return 'noform';
157
	}
158
159
	// Functions you'll need to call.
160
161
	/**
162
	 * PHP5 constructor.
163
	 *
164
	 * @since 2.8.0
165
	 * @access public
166
	 *
167
	 * @param string $id_base         Optional Base ID for the widget, lowercase and unique. If left empty,
168
	 *                                a portion of the widget's class name will be used Has to be unique.
169
	 * @param string $name            Name for the widget displayed on the configuration page.
170
	 * @param array  $widget_options  Optional. Widget options. See wp_register_sidebar_widget() for information
171
	 *                                on accepted arguments. Default empty array.
172
	 * @param array  $control_options Optional. Widget control options. See wp_register_widget_control() for
173
	 *                                information on accepted arguments. Default empty array.
174
	 */
175
	public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
176
		$this->id_base = empty($id_base) ? preg_replace( '/(wp_)?widget_/', '', strtolower(get_class($this)) ) : strtolower($id_base);
177
		$this->name = $name;
178
		$this->option_name = 'widget_' . $this->id_base;
179
		$this->widget_options = wp_parse_args( $widget_options, array( 'classname' => $this->option_name, 'customize_selective_refresh' => false ) );
180
		$this->control_options = wp_parse_args( $control_options, array( 'id_base' => $this->id_base ) );
181
	}
182
183
	/**
184
	 * PHP4 constructor.
185
	 *
186
	 * @since 2.8.0
187
	 * @access public
188
	 *
189
	 * @see __construct()
190
	 *
191
	 * @param string $id_base         Optional Base ID for the widget, lowercase and unique. If left empty,
192
	 *                                a portion of the widget's class name will be used Has to be unique.
193
	 * @param string $name            Name for the widget displayed on the configuration page.
194
	 * @param array  $widget_options  Optional. Widget options. See wp_register_sidebar_widget() for information
195
	 *                                on accepted arguments. Default empty array.
196
	 * @param array  $control_options Optional. Widget control options. See wp_register_widget_control() for
197
	 *                                information on accepted arguments. Default empty array.
198
	 */
199
	public function WP_Widget( $id_base, $name, $widget_options = array(), $control_options = array() ) {
0 ignored issues
show
Using PHP4-style constructors that are named like the class is not recommend; better use the more explicit __construct method.
Loading history...
200
		_deprecated_constructor( 'WP_Widget', '4.3.0', get_class( $this ) );
201
		WP_Widget::__construct( $id_base, $name, $widget_options, $control_options );
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
202
	}
203
204
	/**
205
	 * Constructs name attributes for use in form() fields
206
	 *
207
	 * This function should be used in form() methods to create name attributes for fields
208
	 * to be saved by update()
209
	 *
210
	 * @since 2.8.0
211
	 * @since 4.4.0 Array format field names are now accepted.
212
	 * @access public
213
	 *
214
	 * @param string $field_name Field name
215
	 * @return string Name attribute for $field_name
216
	 */
217
	public function get_field_name($field_name) {
218
		if ( false === $pos = strpos( $field_name, '[' ) ) {
219
			return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']';
220
		} else {
221
			return 'widget-' . $this->id_base . '[' . $this->number . '][' . substr_replace( $field_name, '][', $pos, strlen( '[' ) );
222
		}
223
	}
224
225
	/**
226
	 * Constructs id attributes for use in WP_Widget::form() fields.
227
	 *
228
	 * This function should be used in form() methods to create id attributes
229
	 * for fields to be saved by WP_Widget::update().
230
	 *
231
	 * @since 2.8.0
232
	 * @since 4.4.0 Array format field IDs are now accepted.
233
	 * @access public
234
	 *
235
	 * @param string $field_name Field name.
236
	 * @return string ID attribute for `$field_name`.
237
	 */
238
	public function get_field_id( $field_name ) {
239
		return 'widget-' . $this->id_base . '-' . $this->number . '-' . trim( str_replace( array( '[]', '[', ']' ), array( '', '-', '' ), $field_name ), '-' );
240
	}
241
242
	/**
243
	 * Register all widget instances of this widget class.
244
	 *
245
	 * @since 2.8.0
246
	 * @access public
247
	 */
248
	public function _register() {
249
		$settings = $this->get_settings();
250
		$empty = true;
251
252
		// When $settings is an array-like object, get an intrinsic array for use with array_keys().
253
		if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) {
254
			$settings = $settings->getArrayCopy();
255
		}
256
257
		if ( is_array( $settings ) ) {
258
			foreach ( array_keys( $settings ) as $number ) {
259
				if ( is_numeric( $number ) ) {
260
					$this->_set( $number );
261
					$this->_register_one( $number );
262
					$empty = false;
263
				}
264
			}
265
		}
266
267
		if ( $empty ) {
268
			// If there are none, we register the widget's existence with a generic template.
269
			$this->_set( 1 );
270
			$this->_register_one();
271
		}
272
	}
273
274
	/**
275
	 * Sets the internal order number for the widget instance.
276
	 *
277
	 * @since 2.8.0
278
	 * @access public
279
	 *
280
	 * @param int $number The unique order number of this widget instance compared to other
281
	 *                    instances of the same class.
282
	 */
283
	public function _set($number) {
284
		$this->number = $number;
285
		$this->id = $this->id_base . '-' . $number;
286
	}
287
288
	/**
289
	 * Retrieves the widget display callback.
290
	 *
291
	 * @since 2.8.0
292
	 * @access public
293
	 *
294
	 * @return callable Display callback.
295
	 */
296
	public function _get_display_callback() {
297
		return array($this, 'display_callback');
298
	}
299
300
	/**
301
	 * Retrieves the widget update callback.
302
	 *
303
	 * @since 2.8.0
304
	 * @access public
305
	 *
306
	 * @return callable Update callback.
307
	 */
308
	public function _get_update_callback() {
309
		return array($this, 'update_callback');
310
	}
311
312
	/**
313
	 * Retrieves the form callback.
314
	 *
315
	 * @since 2.8.0
316
	 * @access public
317
	 *
318
	 * @return callable Form callback.
319
	 */
320
	public function _get_form_callback() {
321
		return array($this, 'form_callback');
322
	}
323
324
	/**
325
	 * Determines whether the current request is inside the Customizer preview.
326
	 *
327
	 * If true -- the current request is inside the Customizer preview, then
328
	 * the object cache gets suspended and widgets should check this to decide
329
	 * whether they should store anything persistently to the object cache,
330
	 * to transients, or anywhere else.
331
	 *
332
	 * @since 3.9.0
333
	 * @access public
334
	 *
335
	 * @global WP_Customize_Manager $wp_customize
336
	 *
337
	 * @return bool True if within the Customizer preview, false if not.
338
	 */
339
	public function is_preview() {
340
		global $wp_customize;
341
		return ( isset( $wp_customize ) && $wp_customize->is_preview() ) ;
342
	}
343
344
	/**
345
	 * Generates the actual widget content (Do NOT override).
346
	 *
347
	 * Finds the instance and calls WP_Widget::widget().
348
	 *
349
	 * @since 2.8.0
350
	 * @access public
351
	 *
352
	 * @param array     $args        Display arguments. See WP_Widget::widget() for information
353
	 *                               on accepted arguments.
354
	 * @param int|array $widget_args {
355
	 *     Optional. Internal order number of the widget instance, or array of multi-widget arguments.
356
	 *     Default 1.
357
	 *
358
	 *     @type int $number Number increment used for multiples of the same widget.
359
	 * }
360
	 */
361
	public function display_callback( $args, $widget_args = 1 ) {
362
		if ( is_numeric( $widget_args ) ) {
363
			$widget_args = array( 'number' => $widget_args );
364
		}
365
366
		$widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
367
		$this->_set( $widget_args['number'] );
368
		$instances = $this->get_settings();
369
370
		if ( array_key_exists( $this->number, $instances ) ) {
371
			$instance = $instances[ $this->number ];
372
373
			/**
374
			 * Filters the settings for a particular widget instance.
375
			 *
376
			 * Returning false will effectively short-circuit display of the widget.
377
			 *
378
			 * @since 2.8.0
379
			 *
380
			 * @param array     $instance The current widget instance's settings.
381
			 * @param WP_Widget $this     The current widget instance.
382
			 * @param array     $args     An array of default widget arguments.
383
			 */
384
			$instance = apply_filters( 'widget_display_callback', $instance, $this, $args );
385
386
			if ( false === $instance ) {
387
				return;
388
			}
389
390
			$was_cache_addition_suspended = wp_suspend_cache_addition();
391
			if ( $this->is_preview() && ! $was_cache_addition_suspended ) {
392
				wp_suspend_cache_addition( true );
393
			}
394
395
			$this->widget( $args, $instance );
396
397
			if ( $this->is_preview() ) {
398
				wp_suspend_cache_addition( $was_cache_addition_suspended );
399
			}
400
		}
401
	}
402
403
	/**
404
	 * Handles changed settings (Do NOT override).
405
	 *
406
	 * @since 2.8.0
407
	 * @access public
408
	 *
409
	 * @global array $wp_registered_widgets
410
	 *
411
	 * @param int $deprecated Not used.
412
	 */
413
	public function update_callback( $deprecated = 1 ) {
414
		global $wp_registered_widgets;
415
416
		$all_instances = $this->get_settings();
417
418
		// We need to update the data
419
		if ( $this->updated )
420
			return;
421
422
		if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
423
			// Delete the settings for this instance of the widget
424
			if ( isset($_POST['the-widget-id']) )
425
				$del_id = $_POST['the-widget-id'];
426
			else
427
				return;
428
429
			if ( isset($wp_registered_widgets[$del_id]['params'][0]['number']) ) {
430
				$number = $wp_registered_widgets[$del_id]['params'][0]['number'];
431
432
				if ( $this->id_base . '-' . $number == $del_id )
433
					unset($all_instances[$number]);
434
			}
435
		} else {
436
			if ( isset($_POST['widget-' . $this->id_base]) && is_array($_POST['widget-' . $this->id_base]) ) {
437
				$settings = $_POST['widget-' . $this->id_base];
438
			} elseif ( isset($_POST['id_base']) && $_POST['id_base'] == $this->id_base ) {
439
				$num = $_POST['multi_number'] ? (int) $_POST['multi_number'] : (int) $_POST['widget_number'];
440
				$settings = array( $num => array() );
441
			} else {
442
				return;
443
			}
444
445
			foreach ( $settings as $number => $new_instance ) {
446
				$new_instance = stripslashes_deep($new_instance);
447
				$this->_set($number);
448
449
				$old_instance = isset($all_instances[$number]) ? $all_instances[$number] : array();
450
451
				$was_cache_addition_suspended = wp_suspend_cache_addition();
452
				if ( $this->is_preview() && ! $was_cache_addition_suspended ) {
453
					wp_suspend_cache_addition( true );
454
				}
455
456
				$instance = $this->update( $new_instance, $old_instance );
457
458
				if ( $this->is_preview() ) {
459
					wp_suspend_cache_addition( $was_cache_addition_suspended );
460
				}
461
462
				/**
463
				 * Filters a widget's settings before saving.
464
				 *
465
				 * Returning false will effectively short-circuit the widget's ability
466
				 * to update settings.
467
				 *
468
				 * @since 2.8.0
469
				 *
470
				 * @param array     $instance     The current widget instance's settings.
471
				 * @param array     $new_instance Array of new widget settings.
472
				 * @param array     $old_instance Array of old widget settings.
473
				 * @param WP_Widget $this         The current widget instance.
474
				 */
475
				$instance = apply_filters( 'widget_update_callback', $instance, $new_instance, $old_instance, $this );
476
				if ( false !== $instance ) {
477
					$all_instances[$number] = $instance;
478
				}
479
480
				break; // run only once
481
			}
482
		}
483
484
		$this->save_settings($all_instances);
0 ignored issues
show
It seems like $all_instances defined by $this->get_settings() on line 416 can also be of type object<ArrayIterator> or object<ArrayObject>; however, WP_Widget::save_settings() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
485
		$this->updated = true;
486
	}
487
488
	/**
489
	 * Generates the widget control form (Do NOT override).
490
	 *
491
	 * @since 2.8.0
492
	 * @access public
493
	 *
494
	 * @param int|array $widget_args {
495
	 *     Optional. Internal order number of the widget instance, or array of multi-widget arguments.
496
	 *     Default 1.
497
	 *
498
	 *     @type int $number Number increment used for multiples of the same widget.
499
	 * }
500
	 * @return string|null
501
	 */
502
	public function form_callback( $widget_args = 1 ) {
503
		if ( is_numeric($widget_args) )
504
			$widget_args = array( 'number' => $widget_args );
505
506
		$widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
507
		$all_instances = $this->get_settings();
508
509
		if ( -1 == $widget_args['number'] ) {
510
			// We echo out a form where 'number' can be set later
511
			$this->_set('__i__');
512
			$instance = array();
513
		} else {
514
			$this->_set($widget_args['number']);
515
			$instance = $all_instances[ $widget_args['number'] ];
516
		}
517
518
		/**
519
		 * Filters the widget instance's settings before displaying the control form.
520
		 *
521
		 * Returning false effectively short-circuits display of the control form.
522
		 *
523
		 * @since 2.8.0
524
		 *
525
		 * @param array     $instance The current widget instance's settings.
526
		 * @param WP_Widget $this     The current widget instance.
527
		 */
528
		$instance = apply_filters( 'widget_form_callback', $instance, $this );
529
530
		$return = null;
531
		if ( false !== $instance ) {
532
			$return = $this->form($instance);
533
534
			/**
535
			 * Fires at the end of the widget control form.
536
			 *
537
			 * Use this hook to add extra fields to the widget form. The hook
538
			 * is only fired if the value passed to the 'widget_form_callback'
539
			 * hook is not false.
540
			 *
541
			 * Note: If the widget has no form, the text echoed from the default
542
			 * form method can be hidden using CSS.
543
			 *
544
			 * @since 2.8.0
545
			 *
546
			 * @param WP_Widget $this     The widget instance, passed by reference.
547
			 * @param null      $return   Return null if new fields are added.
548
			 * @param array     $instance An array of the widget's settings.
549
			 */
550
			do_action_ref_array( 'in_widget_form', array( &$this, &$return, $instance ) );
551
		}
552
		return $return;
553
	}
554
555
	/**
556
	 * Registers an instance of the widget class.
557
	 *
558
	 * @since 2.8.0
559
	 * @access public
560
	 *
561
	 * @param integer $number Optional. The unique order number of this widget instance
562
	 *                        compared to other instances of the same class. Default -1.
563
	 */
564
	public function _register_one( $number = -1 ) {
565
		wp_register_sidebar_widget(	$this->id, $this->name,	$this->_get_display_callback(), $this->widget_options, array( 'number' => $number ) );
566
		_register_widget_update_callback( $this->id_base, $this->_get_update_callback(), $this->control_options, array( 'number' => -1 ) );
567
		_register_widget_form_callback(	$this->id, $this->name,	$this->_get_form_callback(), $this->control_options, array( 'number' => $number ) );
568
	}
569
570
	/**
571
	 * Saves the settings for all instances of the widget class.
572
	 *
573
	 * @since 2.8.0
574
	 * @access public
575
	 *
576
	 * @param array $settings Multi-dimensional array of widget instance settings.
577
	 */
578
	public function save_settings( $settings ) {
579
		$settings['_multiwidget'] = 1;
580
		update_option( $this->option_name, $settings );
581
	}
582
583
	/**
584
	 * Retrieves the settings for all instances of the widget class.
585
	 *
586
	 * @since 2.8.0
587
	 * @access public
588
	 *
589
	 * @return array Multi-dimensional array of widget instance settings.
590
	 */
591
	public function get_settings() {
592
593
		$settings = get_option( $this->option_name );
594
595
		if ( false === $settings ) {
596
			if ( isset( $this->alt_option_name ) ) {
597
				$settings = get_option( $this->alt_option_name );
598
			} else {
599
				// Save an option so it can be autoloaded next time.
600
				$this->save_settings( array() );
601
			}
602
		}
603
604
		if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {
605
			$settings = array();
606
		}
607
608
		if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) {
609
			// Old format, convert if single widget.
610
			$settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings );
0 ignored issues
show
It seems like $settings can also be of type object<ArrayIterator> or object<ArrayObject>; however, wp_convert_widget_settings() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
611
		}
612
613
		unset( $settings['_multiwidget'], $settings['__i__'] );
614
		return $settings;
615
	}
616
}
617