Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of Psy Shell.
5
 *
6
 * (c) 2012-2022 Justin Hileman
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
namespace Psy\Sudo;
13
 
14
use PhpParser\Node;
15
use PhpParser\Node\Arg;
16
use PhpParser\Node\Expr\Assign;
17
use PhpParser\Node\Expr\ClassConstFetch;
18
use PhpParser\Node\Expr\MethodCall;
19
use PhpParser\Node\Expr\New_;
20
use PhpParser\Node\Expr\PropertyFetch;
21
use PhpParser\Node\Expr\StaticCall;
22
use PhpParser\Node\Expr\StaticPropertyFetch;
23
use PhpParser\Node\Identifier;
24
use PhpParser\Node\Name;
25
use PhpParser\Node\Name\FullyQualified as FullyQualifiedName;
26
use PhpParser\Node\Scalar\String_;
27
use PhpParser\NodeVisitorAbstract;
28
use Psy\Sudo;
29
 
30
/**
31
 * A PHP Parser node visitor which rewrites property and method access to use
32
 * the Psy\Sudo visibility bypass methods.
33
 *
34
 * @todo handle assigning by reference
35
 */
36
class SudoVisitor extends NodeVisitorAbstract
37
{
38
    const PROPERTY_FETCH = 'fetchProperty';
39
    const PROPERTY_ASSIGN = 'assignProperty';
40
    const METHOD_CALL = 'callMethod';
41
    const STATIC_PROPERTY_FETCH = 'fetchStaticProperty';
42
    const STATIC_PROPERTY_ASSIGN = 'assignStaticProperty';
43
    const STATIC_CALL = 'callStatic';
44
    const CLASS_CONST_FETCH = 'fetchClassConst';
45
    const NEW_INSTANCE = 'newInstance';
46
 
47
    /**
48
     * {@inheritdoc}
49
     *
50
     * @return int|Node|null Replacement node (or special return value)
51
     */
52
    public function enterNode(Node $node)
53
    {
54
        if ($node instanceof PropertyFetch) {
55
            $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name;
56
            $args = [
57
                $node->var,
58
                \is_string($name) ? new String_($name) : $name,
59
            ];
60
 
61
            return $this->prepareCall(self::PROPERTY_FETCH, $args);
62
        } elseif ($node instanceof Assign && $node->var instanceof PropertyFetch) {
63
            $target = $node->var;
64
            $name = $target->name instanceof Identifier ? $target->name->toString() : $target->name;
65
            $args = [
66
                $target->var,
67
                \is_string($name) ? new String_($name) : $name,
68
                $node->expr,
69
            ];
70
 
71
            return $this->prepareCall(self::PROPERTY_ASSIGN, $args);
72
        } elseif ($node instanceof MethodCall) {
73
            $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name;
74
            $args = $node->args;
75
            \array_unshift($args, new Arg(\is_string($name) ? new String_($name) : $name));
76
            \array_unshift($args, new Arg($node->var));
77
 
78
            // not using prepareCall because the $node->args we started with are already Arg instances
79
            return new StaticCall(new FullyQualifiedName(Sudo::class), self::METHOD_CALL, $args);
80
        } elseif ($node instanceof StaticPropertyFetch) {
81
            $class = $node->class instanceof Name ? $node->class->toString() : $node->class;
82
            $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name;
83
            $args = [
84
                \is_string($class) ? new String_($class) : $class,
85
                \is_string($name) ? new String_($name) : $name,
86
            ];
87
 
88
            return $this->prepareCall(self::STATIC_PROPERTY_FETCH, $args);
89
        } elseif ($node instanceof Assign && $node->var instanceof StaticPropertyFetch) {
90
            $target = $node->var;
91
            $class = $target->class instanceof Name ? $target->class->toString() : $target->class;
92
            $name = $target->name instanceof Identifier ? $target->name->toString() : $target->name;
93
            $args = [
94
                \is_string($class) ? new String_($class) : $class,
95
                \is_string($name) ? new String_($name) : $name,
96
                $node->expr,
97
            ];
98
 
99
            return $this->prepareCall(self::STATIC_PROPERTY_ASSIGN, $args);
100
        } elseif ($node instanceof StaticCall) {
101
            $args = $node->args;
102
            $class = $node->class instanceof Name ? $node->class->toString() : $node->class;
103
            $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name;
104
            \array_unshift($args, new Arg(\is_string($name) ? new String_($name) : $name));
105
            \array_unshift($args, new Arg(\is_string($class) ? new String_($class) : $class));
106
 
107
            // not using prepareCall because the $node->args we started with are already Arg instances
108
            return new StaticCall(new FullyQualifiedName(Sudo::class), self::STATIC_CALL, $args);
109
        } elseif ($node instanceof ClassConstFetch) {
110
            $class = $node->class instanceof Name ? $node->class->toString() : $node->class;
111
            $name = $node->name instanceof Identifier ? $node->name->toString() : $node->name;
112
            $args = [
113
                \is_string($class) ? new String_($class) : $class,
114
                \is_string($name) ? new String_($name) : $name,
115
            ];
116
 
117
            return $this->prepareCall(self::CLASS_CONST_FETCH, $args);
118
        } elseif ($node instanceof New_) {
119
            $args = $node->args;
120
            $class = $node->class instanceof Name ? $node->class->toString() : $node->class;
121
            \array_unshift($args, new Arg(\is_string($class) ? new String_($class) : $class));
122
 
123
            // not using prepareCall because the $node->args we started with are already Arg instances
124
            return new StaticCall(new FullyQualifiedName(Sudo::class), self::NEW_INSTANCE, $args);
125
        }
126
    }
127
 
128
    private function prepareCall(string $method, array $args): StaticCall
129
    {
130
        return new StaticCall(new FullyQualifiedName(Sudo::class), $method, \array_map(function ($arg) {
131
            return new Arg($arg);
132
        }, $args));
133
    }
134
}