Completed
Push — master ( ec656c...4bc6db )
by Jacob
04:58
created

Debugger::shutdown()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4286
cc 2
eloc 6
nc 2
nop 0
1
<?
0 ignored issues
show
Security Best Practice introduced by
It is not recommend to use PHP's short opening tag <?, better use <?php, or <?= in case of outputting.

Short opening tags are disabled in PHP’s default configuration. In such a case, all content of this file is output verbatim to the browser without being parsed, or executed.

As a precaution to avoid these problems better use the long opening tag <?php.

Loading history...
2
3
use Particletree\Pqp\Console;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Console.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
4
use Particletree\Pqp\PhpQuickProfiler;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, PhpQuickProfiler.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
5
6
final class Debugger
7
{
8
9
	private static $UNKNOWN_ERROR_FILE		= 'Unknown File';
10
	private static $UNKNOWN_ERROR_LINE		= 'Unknown Line';
11
	private static $UNKNOWN_ERROR_CONTEXT	= 'Unknown Context';
12
13
	private $profiler;
14
	private $display = true;
0 ignored issues
show
Unused Code introduced by
The property $display is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
15
16
	private static $instance;
17
18
	private function __construct()
19
	{
20
		$this->console = new Console();
0 ignored issues
show
Bug introduced by
The property console does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
21
    $this->profiler = new PhpQuickProfiler();
22
    $this->profiler->setConsole($this->console);
23
	}
24
25
	public static function instance()
26
	{
27
		if(!isset(self::$instance))
28
			self::$instance = new Debugger();
29
		return self::$instance;
30
	}
31
32
	public static function log($message)
33
	{
34
		self::instance()->console->logError(new Exception(), 'Gah, this is using Debugger::log()!');
35
		self::instance()->console->log($message);
36
	}
37
38
	public static function logMessage($message)
39
	{
40
		self::instance()->console->log($message);
41
	}
42
43
	public static function logMemory($object = null, $name = '')
44
	{
45
		self::instance()->console->logMemory($object, $name);
46
	}
47
48
	public static function logSpeed($message = '')
49
	{
50
		self::instance()->console->logSpeed($message);
51
	}
52
53
	public static function internal_error($code, $string, $file = null, $line = null, $context = null)
54
	{
55
		if($file == null)
56
			$file = self::$UNKNOWN_ERROR_FILE;
0 ignored issues
show
Unused Code introduced by
$file is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
57
		if($line == null)
58
			$line = self::$UNKNOWN_ERROR_LINE;
0 ignored issues
show
Unused Code introduced by
$line is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
59
		if($context == null)
60
			$context = self::$UNKNOWN_ERROR_CONTEXT;
0 ignored issues
show
Unused Code introduced by
$context is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
61
		
62
		self::instance()->console->logError(new Exception($string), "{$string}... TYPE: {$code}");
63
		
64
		return true;
65
	}
66
67
	public static function shutdown()
68
	{
69
		$error = error_get_last();
70
		
71
		if(isset($error))
72
			self::internal_error($error['type'], $error['message'], $error['file'], $error['line']);
73
		
74
		self::display();
75
		return true;
76
	}
77
78
	public static function hide()
79
	{
80
		self::instance()->display = false;
81
	}
82
83
	public static function display()
0 ignored issues
show
Coding Style introduced by
display uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
84
	{
85
    if ($_COOKIE['debugger'] == 'display' && self::instance()->display) {
86
      $pdo = '';
87
      if (!empty($pdo)) {
88
        $profiles = $pdo->getProfiler()->getProfiles();
0 ignored issues
show
Bug introduced by
The method getProfiler cannot be called on $pdo (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
89
        $profiles = array_filter($profiles, function ($profile) {
90
            return $profile['function'] == 'perform';
91
        });
92
        $profiles = array_map(function ($profile) {
93
            return array(
94
                'sql' => $profile['statement'],
95
                'parameters' => $profile['bind_values'],
96
                'time' => $profile['duration']
97
            );
98
        }, $profiles);
99
        self::instance()->profiler->setProfiledQueries($profiles);
100
      }
101
      self::instance()->profiler->setDisplay(new Particletree\Pqp\Display());
102
      self::instance()->profiler->display($pdo);
103
    }
104
	}
105
106
}
107