Completed
Pull Request — master (#546)
by Richard
09:47
created

Kint_Parser_ClassStatics::parse()   F

Complexity

Conditions 16
Paths 728

Size

Total Lines 98
Code Lines 61

Duplication

Lines 15
Ratio 15.31 %

Importance

Changes 0
Metric Value
cc 16
eloc 61
nc 728
nop 3
dl 15
loc 98
rs 2.3966
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class Kint_Parser_ClassStatics extends Kint_Parser_Plugin
4
{
5
    private static $cache = array();
6
7
    public function getTypes()
8
    {
9
        return array('object');
10
    }
11
12
    public function getTriggers()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
13
    {
14
        return Kint_Parser::TRIGGER_SUCCESS;
15
    }
16
17
    public function parse(&$var, Kint_Object &$o, $trigger)
18
    {
19
        $class = get_class($var);
20
        $reflection = new ReflectionClass($class);
21
22
        // Constants
23
        // TODO: PHP 7.1 allows private consts but reflection doesn't have a way to check them yet
24
        if (!isset(self::$cache[$class])) {
25
            $consts = array();
26
27
            foreach ($reflection->getConstants() as $name => $val) {
28
                $const = Kint_Object::blank($name);
29
                $const->const = true;
30
                $const->depth = $o->depth + 1;
31
                $const->owner_class = $class;
32 View Code Duplication
                if (KINT_PHP53) {
33
                    $const->access_path = '\\'.$class.'::'.$const->name;
34
                } else {
35
                    $const->access_path = $class.'::'.$const->name;
36
                }
37
                $const->operator = Kint_Object::OPERATOR_STATIC;
38
                $const = $this->parser->parse($val, $const);
39
40
                $consts[] = $const;
41
            }
42
43
            self::$cache[$class] = $consts;
44
        }
45
46
        $statics = new Kint_Object_Representation('Static class properties', 'statics');
47
        $statics->contents = self::$cache[$class];
48
49
        // Statics
50
51
        if (!KINT_PHP53) {
52
            $static_map = $reflection->getStaticProperties();
53
        }
54
55
        foreach ($reflection->getProperties(ReflectionProperty::IS_STATIC) as $static) {
56
            $prop = new Kint_Object();
57
            $prop->name = '$'.$static->getName();
58
            $prop->depth = $o->depth + 1;
59
            $prop->static = true;
60
            $prop->operator = Kint_Object::OPERATOR_STATIC;
61
62
            if (KINT_PHP53) {
63
                $prop->owner_class = $static->getDeclaringClass()->name;
64
            } else {
65
                // getDeclaringClass() is broke in old PHP versions, but getProperties() will only
66
                // return accessible properties and we can access them through the parent class so
67
                // we can just put the parent class here. It's not an accurate portrayal of where
68
                // the static comes from, but it shows a working access path so it's good enough
69
                $prop->owner_class = $class;
70
            }
71
72
            $prop->access = Kint_Object::ACCESS_PUBLIC;
73 View Code Duplication
            if ($static->isProtected()) {
74
                $prop->access = Kint_Object::ACCESS_PROTECTED;
75
            } elseif ($static->isPrivate()) {
76
                $prop->access = Kint_Object::ACCESS_PRIVATE;
77
            }
78
79
            if ($this->parser->childHasPath($o, $prop)) {
0 ignored issues
show
Compatibility introduced by
$o of type object<Kint_Object> is not a sub-type of object<Kint_Object_Instance>. It seems like you assume a child class of the class Kint_Object to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
80 View Code Duplication
                if (KINT_PHP53) {
81
                    $prop->access_path = '\\'.$prop->owner_class.'::'.$prop->name;
82
                } else {
83
                    $prop->access_path = $prop->owner_class.'::'.$prop->name;
84
                }
85
            }
86
87
            if (KINT_PHP53) {
88
                $static->setAccessible(true);
89
                $val = $static->getValue();
90
            } else {
91
                switch ($prop->access) {
92
                    case Kint_Object::ACCESS_PUBLIC:
93
                        $val = $static_map[$static->getName()];
0 ignored issues
show
Bug introduced by
The variable $static_map 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...
94
                        break;
95
                    case Kint_Object::ACCESS_PROTECTED:
96
                        $val = $static_map["\0*\0".$static->getName()];
97
                        break;
98
                    case Kint_Object::ACCESS_PRIVATE:
99
                        $val = $static_map["\0".$class."\0".$static->getName()];
100
                        break;
101
                }
102
            }
103
104
            $statics->contents[] = $this->parser->parse($val, $prop);
105
        }
106
107
        if (empty($statics->contents)) {
108
            return;
109
        }
110
111
        usort($statics->contents, array('Kint_Parser_ClassStatics', 'sort'));
112
113
        $o->addRepresentation($statics);
114
    }
115
116
    private static function sort(Kint_Object $a, Kint_Object $b)
117
    {
118
        $sort = ((int) $a->const) - ((int) $b->const);
119
        if ($sort) {
120
            return $sort;
121
        }
122
123
        $sort = Kint_Object::sortByAccess($a, $b);
124
        if ($sort) {
125
            return $sort;
126
        }
127
128
        return Kint_Object_Instance::sortByHierarchy($a->owner_class, $b->owner_class);
129
    }
130
}
131