ZendFunction::getClassName()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
/**
4
 * This file is part of the sj-i/php-profiler package.
5
 *
6
 * (c) sji <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace PhpProfiler\Lib\PhpInternals\Types\Zend;
15
16
use FFI\PhpInternals\zend_function;
17
use PhpProfiler\Lib\PhpInternals\CastedCData;
18
use PhpProfiler\Lib\Process\Pointer\Dereferencable;
19
use PhpProfiler\Lib\Process\Pointer\Dereferencer;
20
use PhpProfiler\Lib\Process\Pointer\Pointer;
21
22
final class ZendFunction implements Dereferencable
23
{
24
    /** @psalm-suppress PropertyNotSetInConstructor */
25
    public int $type;
26
27
    /** @psalm-suppress PropertyNotSetInConstructor */
28
    public ZendOpArray $op_array;
29
30
    /**
31
     * @psalm-suppress PropertyNotSetInConstructor
32
     * @var Pointer<ZendString>|null
33
     */
34
    public ?Pointer $function_name;
35
36
    /**
37
     * @psalm-suppress PropertyNotSetInConstructor
38
     * @var Pointer<ZendClassEntry>|null
39
     */
40
    public ?Pointer $scope;
41
42
    /**
43
     * @param CastedCData<zend_function> $casted_cdata
44
     */
45
    public function __construct(
46
        private CastedCData $casted_cdata,
47
    ) {
48
        unset($this->type);
49
        unset($this->function_name);
50
        unset($this->scope);
51
        unset($this->op_array);
52
    }
53
54
    public function __get(string $field_name): mixed
55
    {
56
        return match ($field_name) {
57
            'type' => $this->type = $this->casted_cdata->casted->type,
58
            'function_name' => $this->function_name
59
                = $this->casted_cdata->casted->common->function_name !== null
60
                    ? Pointer::fromCData(
61
                        ZendString::class,
62
                        $this->casted_cdata->casted->common->function_name,
63
                    )
64
                    : null
65
            ,
66
            'scope' => $this->scope
67
                = $this->casted_cdata->casted->common->scope !== null
68
                    ? Pointer::fromCData(
69
                        ZendClassEntry::class,
70
                        $this->casted_cdata->casted->common->scope,
71
                    )
72
                    : null
73
            ,
74
            'op_array' => $this->op_array = new ZendOpArray($this->casted_cdata->casted->op_array),
75
        };
76
    }
77
78
    public static function getCTypeName(): string
79
    {
80
        return 'zend_function';
81
    }
82
83
    public static function fromCastedCData(
84
        CastedCData $casted_cdata,
85
        Pointer $pointer
86
    ): static {
87
        /** @var CastedCData<zend_function> $casted_cdata */
88
        return new self($casted_cdata);
89
    }
90
91
    public function getFullyQualifiedFunctionName(Dereferencer $dereferencer): string
92
    {
93
        $class_name = $this->getClassName($dereferencer);
94
        $function_name = $this->getFunctionName($dereferencer) ?? '';
95
        if (!is_null($class_name)) {
96
            return $class_name . '::' . $function_name;
97
        }
98
        return $function_name;
99
    }
100
101
    public function getFunctionName(Dereferencer $dereferencer): ?string
102
    {
103
        if ($this->function_name === null) {
104
            return null;
105
        }
106
        $string = $dereferencer->deref($this->function_name);
107
        $val = $string->getValuePointer($this->function_name);
108
        return (string)$dereferencer->deref($val);
109
    }
110
111
    public function getClassName(Dereferencer $dereferencer): ?string
112
    {
113
        if ($this->scope === null) {
114
            return null;
115
        }
116
        $class_entry = $dereferencer->deref($this->scope);
117
        return $class_entry->getClassName($dereferencer);
118
    }
119
120
    public function getFileName(Dereferencer $dereferencer): ?string
121
    {
122
        if ($this->type !== 2) {
123
            return '<internal>';
124
        }
125
        return $this->op_array->getFileName($dereferencer);
126
    }
127
}
128