Completed
Push — master ( b270a4...a33cab )
by Joe
01:59
created

ComCallStack::current()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace PhpWinTools\WmiScripting\Testing\CallStacks;
4
5
use PhpWinTools\Support\COM\ComVariantWrapper;
6
use PhpWinTools\WmiScripting\Collections\ArrayCollection;
7
use PhpWinTools\WmiScripting\Support\ApiObjects\AbstractWbemObject;
8
9
class ComCallStack
10
{
11
    protected static $instance;
12
13
    /** @var array|ComCall[] */
14
    protected $stack;
15
16 1
    public function __construct()
17
    {
18 1
        $this->stack = new ArrayCollection();
0 ignored issues
show
Documentation Bug introduced by
It seems like new PhpWinTools\WmiScrip...tions\ArrayCollection() of type PhpWinTools\WmiScripting...ections\ArrayCollection is incompatible with the declared type PhpWinTools\WmiScripting...lStacks\ComCall[]|array of property $stack.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
19
20 1
        static::$instance = $this;
21 1
    }
22
23
    /**
24
     * @return ComCallStack
25
     */
26 2
    public static function instance()
27
    {
28 2
        return static::$instance ?? new static();
29
    }
30
31 2
    public static function current()
32
    {
33 2
        return static::instance()->getCurrent();
34
    }
35
36 2
    public function getStackCollection()
37
    {
38 2
        return $this->stack;
39
    }
40
41 2
    public function add(...$call)
42
    {
43 2
        $method = null;
44 2
        $arguments = [];
45
46 2
        switch ($type = array_shift($call)) {
47 2
            case '__set':
48 2
            case '__call':
49 2
                $method = array_shift($call);
50 2
                $arguments = $call[0];
51 2
                break;
52 2
            case '__get':
53
            default:
54 2
                if (is_array($call)) {
55 2
                    $method = array_shift($call);
56 2
                    $arguments = $call[0] ?? [];
57
                } else {
58
                    $method = $call;
59
                    $arguments = [];
60
                }
61
62 2
                break;
63
        }
64
65 2
        $backtrace = $this->getBacktrace();
66 2
        $this->stack->add(new ComCall(
67 2
            $type,
68 2
            $method,
69 2
            $arguments,
70 2
            $backtrace['responder'],
71 2
            $backtrace['caller'],
72 2
            $backtrace['detected_caller']
73
        ));
74
75 2
        return $this;
76
    }
77
78 2
    public function getCurrent()
79
    {
80 2
        return $this->stack[count($this->stack) - 1];
81
    }
82
83 2
    protected function getBacktrace()
84
    {
85 2
        $backtrace = new ArrayCollection(debug_backtrace(true));
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $options of debug_backtrace(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
        $backtrace = new ArrayCollection(debug_backtrace(/** @scrutinizer ignore-type */ true));
Loading history...
86
        $wrapper_call_key = key($backtrace->filter(function ($trace, $key) {
87 2
            if ($trace['class'] === ComVariantWrapper::class) {
88 2
                return $key;
89
            }
90
91 2
            return false;
92 2
        })->toArray());
93
94 2
        if ($wrapper_call_key) {
95 2
            $found_detected = false;
96
            $backtrace = $backtrace->filter(function ($trace, $key) use ($wrapper_call_key, &$found_detected) {
97 2
                if (!$found_detected
98 2
                    && $key > $wrapper_call_key + 1
99 2
                    && array_key_exists(AbstractWbemObject::class, class_parents($trace['class']))
100
                ) {
101 2
                    return $found_detected = true;
102
                }
103
104 2
                return $key === $wrapper_call_key || $key === $wrapper_call_key + 1;
105
            })->values()->map(function ($trace) {
106 2
                return new ComTraceSubject(
107 2
                    $trace['file'],
108 2
                    $trace['class'],
109 2
                    $trace['function'],
110 2
                    $trace['args'],
111 2
                    isset($trace['object']) ? get_class($trace['object']) : null
112
                );
113 2
            });
114
115
            return [
116 2
                'responder'         => $backtrace[0],
117 2
                'caller'            => $backtrace[1] ?? null,
118 2
                'detected_caller'   => $backtrace[2] ?? null,
119
            ];
120
        }
121
122
        return [
123
            'responder'         => null,
124
            'caller'            => null,
125
            'detected_caller'   => null,
126
        ];
127
    }
128
}
129