ComCallStack::instance()   A
last analyzed

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
    public static function newInstance()
24
    {
25
        return static::$instance = new static();
26 2
    }
27
28 2
    /**
29
     * @return ComCallStack
30
     */
31 2
    public static function instance()
32
    {
33 2
        return static::$instance ?? new static();
34
    }
35
36 2
    public static function current()
37
    {
38 2
        return static::instance()->getCurrent();
39
    }
40
41 2
    public function getStackCollection()
42
    {
43 2
        return $this->stack;
44 2
    }
45
46 2
    public function add(...$call)
47 2
    {
48 2
        $method = null;
49 2
        $arguments = [];
50 2
51 2
        switch ($type = array_shift($call)) {
52 2
            case '__set':
53
            case '__call':
54 2
                $method = array_shift($call);
55 2
                $arguments = $call[0];
56 2
                break;
57
            case '__get':
58
            default:
59
                if (is_array($call)) {
60
                    $method = array_shift($call);
61
                    $arguments = $call[0] ?? [];
62 2
                } else {
63
                    $method = $call;
64
                    $arguments = [];
65 2
                }
66 2
67 2
                break;
68 2
        }
69 2
70 2
        $backtrace = $this->getBacktrace();
71 2
        $this->stack->add(new ComCall(
72 2
            $type,
73
            $method,
74
            $arguments,
75 2
            $backtrace['responder'],
76
            $backtrace['caller'],
77
            $backtrace['detected_caller']
78 2
        ));
79
80 2
        return $this;
81
    }
82
83 2
    public function getCurrent()
84
    {
85 2
        return $this->stack[count($this->stack) - 1];
86
    }
87 2
88 2
    protected function getBacktrace()
89
    {
90
        $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

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