Completed
Push — master ( 37398b...f83de7 )
by Michael
10:48 queued 07:15
created

PhpSecInfo::__construct()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 20
nc 8
nop 1
dl 0
loc 30
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * Main class file
4
 *
5
 * @package PhpSecInfo
6
 * @author Ed Finkler <[email protected]>
7
 */
8
9
10
/**
11
 * The default language setting if none is set/retrievable
12
 *
13
 */
14
define ('PHPSECINFO_LANG_DEFAULT', 'en');
15
16
/**
17
 * a general version string to differentiate releases
18
 *
19
 */
20
define ('PHPSECINFO_VERSION', '0.2.2');
21
22
/**
23
 * a YYYYMMDD date string to indicate "build" date
24
 *
25
 */
26
define ('PHPSECINFO_BUILD', '20080723');
27
28
/**
29
 * Homepage for phpsecinfo project
30
 *
31
 */
32
define ('PHPSECINFO_URL', 'http://phpsecinfo.com');
33
34
/**
35
 * The base folder where views are stored.  Include trailing slash
36
 *
37
 */
38
define('PHPSECINFO_VIEW_DIR_DEFAULT', 'View/');
39
40
41
/**
42
 * The default format, used to load the proper view.
43
 */
44
define('PHPSECINFO_FORMAT_DEFAULT', 'Html');
45
46
47
/**
48
 * The base directory, used to resolve requires and includes
49
 */
50
define('PHPSECINFO_BASE_DIR', dirname(__FILE__));
51
52
/**
53
 * This is the main class for the phpsecinfo system.  It's responsible for
54
 * dynamically loading tests, running those tests, and generating the results
55
 * output
56
 *
57
 * Example:
58
 * <code>
59
 * <?php require_once(PHPSECINFO_BASE_DIR.'/PhpSecInfo.php'); ?>
60
 * <?php phpsecinfo(); ?>
61
 * </code>
62
 *
63
 * If you want to capture the output, or just grab the test results and display them
64
 * in your own way, you'll need to do slightly more work.
65
 *
66
 * Example:
67
 * <code>
68
 * require_once(PHPSECINFO_BASE_DIR.'/PhpSecInfo.php');
69
 * // instantiate the class
70
 * $psi = new PhpSecInfo();
71
 *
72
 * // load and run all tests
73
 * $psi->loadAndRun();
74
 *
75
 * // grab the results as a multidimensional array
76
 * $results = $psi->getResultsAsArray();
77
 * echo "<pre>"; echo print_r($results, true); echo "</pre>";
78
 *
79
 * // grab the standard results output as a string
80
 * $html = $psi->getOutput();
81
 *
82
 * // send it to the browser
83
 * echo $html;
84
 * </code>
85
 *
86
 *
87
 * The procedural function "phpsecinfo" is defined below this class.
88
 * @see phpsecinfo()
89
 *
90
 * @author Ed Finkler <[email protected]>
91
 *
92
 * see CHANGELOG for changes
93
 *
94
 */
95
class PhpSecInfo
0 ignored issues
show
Coding Style Compatibility introduced by
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.

Loading history...
96
{
97
98
	/**
99
	 * An array of tests to run
100
	 *
101
	 * @var array PhpSecInfo_Test
102
	 */
103
	var $tests_to_run = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $tests_to_run.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
104
105
106
	/**
107
	 * An array of results.  Each result is an associative array:
108
	 * <code>
109
	 * $result['result'] = PHPSECINFO_TEST_RESULT_NOTICE;
110
	 * $result['message'] = "a string describing the test results and what they mean";
111
	 * </code>
112
	 *
113
	 * @var array
114
	 */
115
	var $test_results = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $test_results.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
116
117
118
	/**
119
	 * An array of tests that were not run
120
	 *
121
	 * <code>
122
	 * $result['result'] = PHPSECINFO_TEST_RESULT_NOTRUN;
123
	 * $result['message'] = "a string explaining why the test was not run";
124
	 * </code>
125
	 *
126
	 * @var array
127
	 */
128
	var $tests_not_run = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $tests_not_run.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
129
130
131
	/**
132
	 * The language code used.  Defaults to PHPSECINFO_LANG_DEFAULT, which
133
	 * is 'en'
134
	 *
135
	 * @var string
136
	 * @see PHPSECINFO_LANG_DEFAULT
137
	 */
138
	var $language = PHPSECINFO_LANG_DEFAULT;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $language.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
139
140
141
	/**
142
	 * An array of integers recording the number of test results in each category.  Categories can include
143
	 * some or all of the PHPSECINFO_TEST_* constants.  Constants are the keys, # of results are the values.
144
	 *
145
	 * @var array
146
	 */
147
	var $result_counts = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $result_counts.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
148
149
150
	/**
151
	 * The number of tests that have been run
152
	 *
153
	 * @var integer
154
	 */
155
	var $num_tests_run = 0;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $num_tests_run.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
156
157
158
	/**
159
	 * The base directory for phpsecinfo. Set within the constructor. Paths are resolved from this.
160
	 * @var string
161
	 */
162
	var $_base_dir;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $_base_dir.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
163
164
165
	/**
166
	 * The directory PHPSecInfo will look for views.  It defaults to the value
167
	 * in PHPSECINFO_VIEW_DIR_DEFAULT, but can be changed with the setViewDirectory()
168
	 * method.
169
	 *
170
	 * @var string
171
	 */
172
	var $_view_directory;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $_view_directory.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
173
174
175
	/**
176
	 * The output format, used to load the proper view
177
	 *
178
	 * @var string
179
	 **/
180
	var $_format;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $_format.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
181
182
	/**
183
	 * Constructor
184
	 *
185
	 * @return PhpSecInfo
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
186
	 */
187
	function __construct($opts = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
188
		
189
		$this->_base_dir = dirname(__FILE__);
190
		
191
		if ($opts) {
192
			if (isset($opts['view_directory'])) {
193
				$this->setViewDirectory($opts['view_directory']);
194
			} else {
195
				$this->setViewDirectory(dirname(__FILE__).DIRECTORY_SEPARATOR . PHPSECINFO_VIEW_DIR_DEFAULT);
196
			}
197
			
198
			if (isset($opts['format'])) {
199
				$this->setFormat($opts['format']);
200
			} else {
201
				if (!strcasecmp(PHP_SAPI, 'cli')) {
202
					$this->setFormat('Cli');
203
				} else {
204
					$this->setFormat(PHPSECINFO_FORMAT_DEFAULT);
205
				}
206
			}
207
			
208
		} else { /* Use defaults */
209
			$this->setViewDirectory(dirname(__FILE__).DIRECTORY_SEPARATOR . PHPSECINFO_VIEW_DIR_DEFAULT);
210
			if (!strcasecmp(PHP_SAPI, 'cli')) {
211
				$this->setFormat('Cli');
212
			} else {
213
				$this->setFormat(PHPSECINFO_FORMAT_DEFAULT);
214
			}
215
		}
216
	}
217
218
219
	/**
220
	 * recurses through the Test subdir and includes classes in each test group subdir,
221
	 * then builds an array of classnames for the tests that will be run
222
	 *
223
	 */
224
	function loadTests() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225
226
		$test_root = dir(dirname(__FILE__).DIRECTORY_SEPARATOR.'Test');
227
228
		//echo "<pre>"; echo print_r($test_root, true); echo "</pre>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
229
230
		while (false !== ($entry = $test_root->read())) {
231
			if ( is_dir($test_root->path.DIRECTORY_SEPARATOR.$entry) && !preg_match('~^(\.|_vti)(.*)$~', $entry) ) {
0 ignored issues
show
Bug introduced by
The property path does not seem to exist in Directory.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
232
				$test_dirs[] = $entry;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$test_dirs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $test_dirs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
233
			}
234
		}
235
		//echo "<pre>"; echo print_r($test_dirs, true); echo "</pre>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
236
237
		// include_once all files in each test dir
238
		foreach ($test_dirs as $test_dir) {
0 ignored issues
show
Bug introduced by
The variable $test_dirs does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
239
			$this_dir = dir($test_root->path.DIRECTORY_SEPARATOR.$test_dir);
240
241
			while (false !== ($entry = $this_dir->read())) {
242
				if (!is_dir($this_dir->path.DIRECTORY_SEPARATOR.$entry)) {
243
					include_once $this_dir->path.DIRECTORY_SEPARATOR.$entry;
244
					$classNames[] = "PhpSecInfo_Test_".$test_dir."_".basename($entry, '.php');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$classNames was never initialized. Although not strictly required by PHP, it is generally a good practice to add $classNames = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
245
				}
246
			}
247
248
		}
249
250
		// modded this to not throw a PHP5 STRICT notice, although I don't like passing by value here
251
		$this->tests_to_run = $classNames;
0 ignored issues
show
Bug introduced by
The variable $classNames does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
252
	}
253
254
255
	/**
256
	 * This runs the tests in the tests_to_run array and
257
	 * places returned data in the following arrays/scalars:
258
	 * - $this->test_results
259
	 * - $this->result_counts
260
	 * - $this->num_tests_run
261
	 * - $this->tests_not_run;
262
	 *
263
	 */
264
	function runTests() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
265
		// initialize a bunch of arrays
266
		$this->test_results  = array();
267
		$this->result_counts = array();
268
		$this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN] = 0;
269
		$this->num_tests_run = 0;
270
271
		foreach ($this->tests_to_run as $testClass) {
272
273
			/**
274
			 * @var $test PhpSecInfo_Test
275
			 */
276
			$test = new $testClass();
277
278
			if ($test->isTestable()) {
279
				$test->test();
280
				$rs = array(	'result' => $test->getResult(),
281
							'message' => $test->getMessage(),
282
							'value_current' => $test->getCurrentTestValue(),
283
							'value_recommended' => $test->getRecommendedTestValue(),
284
							'moreinfo_url' => $test->getMoreInfoURL(),
285
						);
286
				$this->test_results[$test->getTestGroup()][$test->getTestName()] = $rs;
287
288
				// initialize if not yet set
289
				if (!isset ($this->result_counts[$rs['result']]) ) {
290
					$this->result_counts[$rs['result']] = 0;
291
				}
292
293
				$this->result_counts[$rs['result']]++;
294
				$this->num_tests_run++;
295
			} else {
296
				$rs = array(	'result' => $test->getResult(),
297
							'message' => $test->getMessage(),
298
							'value_current' => NULL,
299
							'value_recommended' => NULL,
300
							'moreinfo_url' => $test->getMoreInfoURL(),
301
						);
302
				$this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN]++;
303
				$this->tests_not_run[$test->getTestGroup()."::".$test->getTestName()] = $rs;
304
			}
305
		}
306
	}
307
308
309
	/**
310
	 * This is the main output method.  The look and feel mimics phpinfo()
311
	 *
312
	 */
313
	function renderOutput($page_title="Security Information About PHP") {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
314
		/**
315
		 * We need to use PhpSecInfo_Test::getBooleanIniValue() below
316
		 * @see PhpSecInfo_Test::getBooleanIniValue()
317
		 */
318
		if (!class_exists('PhpSecInfo_Test')) {
319
			include( dirname(__FILE__).DIRECTORY_SEPARATOR.'Test'.DIRECTORY_SEPARATOR.'Test.php');
320
		}
321
		$this->loadView($this->_format);
322
	}
323
324
325
	/**
326
	 * This is a helper method that makes it easy to output tables of test results
327
	 * for a given test group
328
	 *
329
	 * @param string $group_name
330
	 * @param array $group_results
331
	 */
332
	function _outputRenderTable($group_name, $group_results) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
333
334
		// exit out if $group_results was empty or not an array.  This sorta seems a little hacky...
335
		if (!is_array($group_results) || sizeof($group_results) < 1) {
336
			return false;
337
		}
338
339
		ksort($group_results);
340
341
		$this->loadView($this->_format.'/Result', array('group_name'=>$group_name, 'group_results'=>$group_results));
342
343
		return true;
344
	}
345
346
347
348
	/**
349
	 * This outputs a table containing a summary of the test results (counts and % in each result type)
350
	 *
351
	 * @see PHPSecInfo::_outputRenderTable()
352
	 * @see PHPSecInfo::_outputGetResultTypeFromCode()
353
	 */
354
	function _outputRenderStatsTable() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
355
356
		foreach($this->result_counts as $code=>$val) {
357
			if ($code != PHPSECINFO_TEST_RESULT_NOTRUN) {
358
				$percentage = round($val/$this->num_tests_run * 100,2);
359
				$result_type = $this->_outputGetResultTypeFromCode($code);
360
				$stats[$result_type] = array( 'count' => $val,
0 ignored issues
show
Coding Style Comprehensibility introduced by
$stats was never initialized. Although not strictly required by PHP, it is generally a good practice to add $stats = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
361
											'result' => $code,
362
											'message' => "$val out of {$this->num_tests_run} ($percentage%)");
363
			}
364
		}
365
366
		$this->_outputRenderTable('Test Results Summary', $stats);
0 ignored issues
show
Bug introduced by
The variable $stats does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
367
368
	}
369
370
371
372
	/**
373
	 * This outputs a table containing a summary or test that were not executed, and the reasons why they were skipped
374
	 *
375
	 * @see PHPSecInfo::_outputRenderTable()
376
	 */
377
	function _outputRenderNotRunTable() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
378
379
		$this->_outputRenderTable('Tests Not Run', $this->tests_not_run);
380
381
	}
382
383
384
385
386
	/**
387
	 * This is a helper function that returns a CSS class corresponding to
388
	 * the result code the test returned.  This allows us to color-code
389
	 * results
390
	 *
391
	 * @param integer $code
392
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
393
	 */
394 View Code Duplication
	function _outputGetCssClassFromResult($code) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
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.

Loading history...
395
396
		switch ($code) {
397
			case PHPSECINFO_TEST_RESULT_OK:
398
				return 'value-ok';
399
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
400
401
			case PHPSECINFO_TEST_RESULT_NOTICE:
402
				return 'value-notice';
403
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
404
405
			case PHPSECINFO_TEST_RESULT_WARN:
406
				return 'value-warn';
407
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
408
409
			case PHPSECINFO_TEST_RESULT_NOTRUN:
410
				return 'value-notrun';
411
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
412
413
			case PHPSECINFO_TEST_RESULT_ERROR:
414
				return 'value-error';
415
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
416
417
			default:
418
				return 'value-notrun';
419
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
420
		}
421
422
	}
423
424
425
426
	/**
427
	 * This is a helper function that returns a label string corresponding to
428
	 * the result code the test returned.  This is mainly used for the Test
429
	 * Results Summary table.
430
	 *
431
	 * @see PHPSecInfo::_outputRenderStatsTable()
432
	 * @param integer $code
433
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
434
	 */
435 View Code Duplication
	function _outputGetResultTypeFromCode($code) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
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.

Loading history...
436
437
		switch ($code) {
438
			case PHPSECINFO_TEST_RESULT_OK:
439
				return 'Pass';
440
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
441
442
			case PHPSECINFO_TEST_RESULT_NOTICE:
443
				return 'Notice';
444
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
445
446
			case PHPSECINFO_TEST_RESULT_WARN:
447
				return 'Warning';
448
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
449
450
			case PHPSECINFO_TEST_RESULT_NOTRUN:
451
				return 'Not Run';
452
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
453
454
			case PHPSECINFO_TEST_RESULT_ERROR:
455
				return 'Error';
456
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
457
458
			default:
459
				return 'Invalid Result Code';
460
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
461
		}
462
463
	}
464
465
466
	/**
467
	 * Loads and runs all the tests
468
	 *
469
	 * As loading, then running, is a pretty common process, this saves a extra method call
470
	 *
471
	 * @since 0.1.1
472
	 *
473
	 */
474
	function loadAndRun() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
475
		$this->loadTests();
476
		$this->runTests();
477
	}
478
479
480
	/**
481
	 * returns an associative array of test data.  Four keys are set:
482
	 * - test_results  (array)
483
	 * - tests_not_run (array)
484
	 * - result_counts (array)
485
	 * - num_tests_run (integer)
486
	 *
487
	 * note that this must be called after tests are loaded and run
488
	 *
489
	 * @since 0.1.1
490
	 * @return array
491
	 */
492
	function getResultsAsArray() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
493
		$results = array();
494
495
		$results['test_results'] = $this->test_results;
496
		$results['tests_not_run'] = $this->tests_not_run;
497
		$results['result_counts'] = $this->result_counts;
498
		$results['num_tests_run'] = $this->num_tests_run;
499
500
		return $results;
501
	}
502
503
504
505
	/**
506
	 * returns the standard output as a string instead of echoing it to the browser
507
	 *
508
	 * note that this must be called after tests are loaded and run
509
	 *
510
	 * @since 0.1.1
511
	 *
512
	 * @return string
513
	 */
514
	function getOutput() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
515
		ob_start();
516
		$this->renderOutput();
517
		$output = ob_get_clean();
518
		return $output;
519
	}
520
521
522
	/**
523
	 * A very, very simple "view" system
524
	 *
525
	 */
526
	function loadView($view_name, $data=null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
527
		if ($data != null) {
528
			extract($data);
529
		}
530
531
		$view_file = $this->getViewDirectory().$view_name.".php";
532
533
		if ( file_exists($view_file) && is_readable($view_file) ) {
534
			ob_start();
535
			include $view_file;
536
			echo ob_get_clean();
537
		} else {
538
			user_error("The view '{$view_file}' either does not exist or is not readable", E_USER_WARNING);
539
		}
540
541
542
	}
543
544
545
	/**
546
	 * Returns the current view directory
547
	 *
548
	 * @return string
549
	 */
550
	function getViewDirectory() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
551
		return $this->_view_directory;
552
	}
553
554
555
	/**
556
	 * Sets the directory that PHPSecInfo will look in for views
557
	 *
558
	 * @param string $newdir
559
	 */
560
	function setViewDirectory($newdir) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
561
		$this->_view_directory = $newdir;
562
	}
563
564
565
566
567
	function getFormat() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
568
		return $this->_format;
569
	}
570
571
572
	function setFormat($format) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
573
		$this->_format = $format;
574
	}
575
576
}
577
578
579
580
581
/**
582
 * A globally-available function that runs the tests and creates the result page
583
 *
584
 */
585
function phpsecinfo() {
586
	// modded this to not throw a PHP5 STRICT notice, although I don't like passing by value here
587
	$psi = new PhpSecInfo();
588
	$psi->loadAndRun();
589
	$psi->renderOutput();
590
}
591
592