Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | 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
 *
200 lars 6
 * (c) 2012-2023 Justin Hileman
148 lars 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;
13
 
14
/**
15
 * The Shell execution context.
16
 *
17
 * This class encapsulates the current variables, most recent return value and
18
 * exception, and the current namespace.
19
 */
20
class Context
21
{
22
    private static $specialNames = ['_', '_e', '__out', '__psysh__', 'this'];
23
 
24
    // Include a very limited number of command-scope magic variable names.
25
    // This might be a bad idea, but future me can sort it out.
26
    private static $commandScopeNames = [
27
        '__function', '__method', '__class', '__namespace', '__file', '__line', '__dir',
28
    ];
29
 
30
    private $scopeVariables = [];
31
    private $commandScopeVariables = [];
32
    private $returnValue;
33
    private $lastException;
34
    private $lastStdout;
35
    private $boundObject;
36
    private $boundClass;
37
 
38
    /**
39
     * Get a context variable.
40
     *
41
     * @throws \InvalidArgumentException If the variable is not found in the current context
42
     *
43
     * @param string $name
44
     *
45
     * @return mixed
46
     */
47
    public function get(string $name)
48
    {
49
        switch ($name) {
50
            case '_':
51
                return $this->returnValue;
52
 
53
            case '_e':
54
                if (isset($this->lastException)) {
55
                    return $this->lastException;
56
                }
57
                break;
58
 
59
            case '__out':
60
                if (isset($this->lastStdout)) {
61
                    return $this->lastStdout;
62
                }
63
                break;
64
 
65
            case 'this':
66
                if (isset($this->boundObject)) {
67
                    return $this->boundObject;
68
                }
69
                break;
70
 
71
            case '__function':
72
            case '__method':
73
            case '__class':
74
            case '__namespace':
75
            case '__file':
76
            case '__line':
77
            case '__dir':
78
                if (\array_key_exists($name, $this->commandScopeVariables)) {
79
                    return $this->commandScopeVariables[$name];
80
                }
81
                break;
82
 
83
            default:
84
                if (\array_key_exists($name, $this->scopeVariables)) {
85
                    return $this->scopeVariables[$name];
86
                }
87
                break;
88
        }
89
 
90
        throw new \InvalidArgumentException('Unknown variable: $'.$name);
91
    }
92
 
93
    /**
94
     * Get all defined variables.
95
     */
96
    public function getAll(): array
97
    {
98
        return \array_merge($this->scopeVariables, $this->getSpecialVariables());
99
    }
100
 
101
    /**
102
     * Get all defined magic variables: $_, $_e, $__out, $__class, $__file, etc.
103
     */
104
    public function getSpecialVariables(): array
105
    {
106
        $vars = [
107
            '_' => $this->returnValue,
108
        ];
109
 
110
        if (isset($this->lastException)) {
111
            $vars['_e'] = $this->lastException;
112
        }
113
 
114
        if (isset($this->lastStdout)) {
115
            $vars['__out'] = $this->lastStdout;
116
        }
117
 
118
        if (isset($this->boundObject)) {
119
            $vars['this'] = $this->boundObject;
120
        }
121
 
122
        return \array_merge($vars, $this->commandScopeVariables);
123
    }
124
 
125
    /**
126
     * Set all scope variables.
127
     *
128
     * This method does *not* set any of the magic variables: $_, $_e, $__out,
129
     * $__class, $__file, etc.
130
     *
131
     * @param array $vars
132
     */
133
    public function setAll(array $vars)
134
    {
135
        foreach (self::$specialNames as $key) {
136
            unset($vars[$key]);
137
        }
138
 
139
        foreach (self::$commandScopeNames as $key) {
140
            unset($vars[$key]);
141
        }
142
 
143
        $this->scopeVariables = $vars;
144
    }
145
 
146
    /**
147
     * Set the most recent return value.
148
     *
149
     * @param mixed $value
150
     */
151
    public function setReturnValue($value)
152
    {
153
        $this->returnValue = $value;
154
    }
155
 
156
    /**
157
     * Get the most recent return value.
158
     *
159
     * @return mixed
160
     */
161
    public function getReturnValue()
162
    {
163
        return $this->returnValue;
164
    }
165
 
166
    /**
167
     * Set the most recent Exception or Error.
168
     *
169
     * @param \Throwable $e
170
     */
171
    public function setLastException(\Throwable $e)
172
    {
173
        $this->lastException = $e;
174
    }
175
 
176
    /**
177
     * Get the most recent Exception or Error.
178
     *
179
     * @throws \InvalidArgumentException If no Exception has been caught
180
     *
181
     * @return \Throwable|null
182
     */
183
    public function getLastException()
184
    {
185
        if (!isset($this->lastException)) {
186
            throw new \InvalidArgumentException('No most-recent exception');
187
        }
188
 
189
        return $this->lastException;
190
    }
191
 
192
    /**
193
     * Set the most recent output from evaluated code.
194
     *
195
     * @param string $lastStdout
196
     */
197
    public function setLastStdout(string $lastStdout)
198
    {
199
        $this->lastStdout = $lastStdout;
200
    }
201
 
202
    /**
203
     * Get the most recent output from evaluated code.
204
     *
205
     * @throws \InvalidArgumentException If no output has happened yet
206
     *
207
     * @return string|null
208
     */
209
    public function getLastStdout()
210
    {
211
        if (!isset($this->lastStdout)) {
212
            throw new \InvalidArgumentException('No most-recent output');
213
        }
214
 
215
        return $this->lastStdout;
216
    }
217
 
218
    /**
219
     * Set the bound object ($this variable) for the interactive shell.
220
     *
221
     * Note that this unsets the bound class, if any exists.
222
     *
223
     * @param object|null $boundObject
224
     */
225
    public function setBoundObject($boundObject)
226
    {
227
        $this->boundObject = \is_object($boundObject) ? $boundObject : null;
228
        $this->boundClass = null;
229
    }
230
 
231
    /**
232
     * Get the bound object ($this variable) for the interactive shell.
233
     *
234
     * @return object|null
235
     */
236
    public function getBoundObject()
237
    {
238
        return $this->boundObject;
239
    }
240
 
241
    /**
242
     * Set the bound class (self) for the interactive shell.
243
     *
244
     * Note that this unsets the bound object, if any exists.
245
     *
246
     * @param string|null $boundClass
247
     */
248
    public function setBoundClass($boundClass)
249
    {
250
        $this->boundClass = (\is_string($boundClass) && $boundClass !== '') ? $boundClass : null;
251
        $this->boundObject = null;
252
    }
253
 
254
    /**
255
     * Get the bound class (self) for the interactive shell.
256
     *
257
     * @return string|null
258
     */
259
    public function getBoundClass()
260
    {
261
        return $this->boundClass;
262
    }
263
 
264
    /**
265
     * Set command-scope magic variables: $__class, $__file, etc.
266
     *
267
     * @param array $commandScopeVariables
268
     */
269
    public function setCommandScopeVariables(array $commandScopeVariables)
270
    {
271
        $vars = [];
272
        foreach ($commandScopeVariables as $key => $value) {
273
            // kind of type check
274
            if (\is_scalar($value) && \in_array($key, self::$commandScopeNames)) {
275
                $vars[$key] = $value;
276
            }
277
        }
278
 
279
        $this->commandScopeVariables = $vars;
280
    }
281
 
282
    /**
283
     * Get command-scope magic variables: $__class, $__file, etc.
284
     */
285
    public function getCommandScopeVariables(): array
286
    {
287
        return $this->commandScopeVariables;
288
    }
289
 
290
    /**
291
     * Get unused command-scope magic variables names: __class, __file, etc.
292
     *
293
     * This is used by the shell to unset old command-scope variables after a
294
     * new batch is set.
295
     *
296
     * @return array Array of unused variable names
297
     */
298
    public function getUnusedCommandScopeVariableNames(): array
299
    {
300
        return \array_diff(self::$commandScopeNames, \array_keys($this->commandScopeVariables));
301
    }
302
 
303
    /**
304
     * Check whether a variable name is a magic variable.
305
     *
306
     * @param string $name
307
     */
308
    public static function isSpecialVariableName(string $name): bool
309
    {
310
        return \in_array($name, self::$specialNames) || \in_array($name, self::$commandScopeNames);
311
    }
312
}