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;
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
     * @return array
97
     */
98
    public function getAll(): array
99
    {
100
        return \array_merge($this->scopeVariables, $this->getSpecialVariables());
101
    }
102
 
103
    /**
104
     * Get all defined magic variables: $_, $_e, $__out, $__class, $__file, etc.
105
     *
106
     * @return array
107
     */
108
    public function getSpecialVariables(): array
109
    {
110
        $vars = [
111
            '_' => $this->returnValue,
112
        ];
113
 
114
        if (isset($this->lastException)) {
115
            $vars['_e'] = $this->lastException;
116
        }
117
 
118
        if (isset($this->lastStdout)) {
119
            $vars['__out'] = $this->lastStdout;
120
        }
121
 
122
        if (isset($this->boundObject)) {
123
            $vars['this'] = $this->boundObject;
124
        }
125
 
126
        return \array_merge($vars, $this->commandScopeVariables);
127
    }
128
 
129
    /**
130
     * Set all scope variables.
131
     *
132
     * This method does *not* set any of the magic variables: $_, $_e, $__out,
133
     * $__class, $__file, etc.
134
     *
135
     * @param array $vars
136
     */
137
    public function setAll(array $vars)
138
    {
139
        foreach (self::$specialNames as $key) {
140
            unset($vars[$key]);
141
        }
142
 
143
        foreach (self::$commandScopeNames as $key) {
144
            unset($vars[$key]);
145
        }
146
 
147
        $this->scopeVariables = $vars;
148
    }
149
 
150
    /**
151
     * Set the most recent return value.
152
     *
153
     * @param mixed $value
154
     */
155
    public function setReturnValue($value)
156
    {
157
        $this->returnValue = $value;
158
    }
159
 
160
    /**
161
     * Get the most recent return value.
162
     *
163
     * @return mixed
164
     */
165
    public function getReturnValue()
166
    {
167
        return $this->returnValue;
168
    }
169
 
170
    /**
171
     * Set the most recent Exception or Error.
172
     *
173
     * @param \Throwable $e
174
     */
175
    public function setLastException(\Throwable $e)
176
    {
177
        $this->lastException = $e;
178
    }
179
 
180
    /**
181
     * Get the most recent Exception or Error.
182
     *
183
     * @throws \InvalidArgumentException If no Exception has been caught
184
     *
185
     * @return \Throwable|null
186
     */
187
    public function getLastException()
188
    {
189
        if (!isset($this->lastException)) {
190
            throw new \InvalidArgumentException('No most-recent exception');
191
        }
192
 
193
        return $this->lastException;
194
    }
195
 
196
    /**
197
     * Set the most recent output from evaluated code.
198
     *
199
     * @param string $lastStdout
200
     */
201
    public function setLastStdout(string $lastStdout)
202
    {
203
        $this->lastStdout = $lastStdout;
204
    }
205
 
206
    /**
207
     * Get the most recent output from evaluated code.
208
     *
209
     * @throws \InvalidArgumentException If no output has happened yet
210
     *
211
     * @return string|null
212
     */
213
    public function getLastStdout()
214
    {
215
        if (!isset($this->lastStdout)) {
216
            throw new \InvalidArgumentException('No most-recent output');
217
        }
218
 
219
        return $this->lastStdout;
220
    }
221
 
222
    /**
223
     * Set the bound object ($this variable) for the interactive shell.
224
     *
225
     * Note that this unsets the bound class, if any exists.
226
     *
227
     * @param object|null $boundObject
228
     */
229
    public function setBoundObject($boundObject)
230
    {
231
        $this->boundObject = \is_object($boundObject) ? $boundObject : null;
232
        $this->boundClass = null;
233
    }
234
 
235
    /**
236
     * Get the bound object ($this variable) for the interactive shell.
237
     *
238
     * @return object|null
239
     */
240
    public function getBoundObject()
241
    {
242
        return $this->boundObject;
243
    }
244
 
245
    /**
246
     * Set the bound class (self) for the interactive shell.
247
     *
248
     * Note that this unsets the bound object, if any exists.
249
     *
250
     * @param string|null $boundClass
251
     */
252
    public function setBoundClass($boundClass)
253
    {
254
        $this->boundClass = (\is_string($boundClass) && $boundClass !== '') ? $boundClass : null;
255
        $this->boundObject = null;
256
    }
257
 
258
    /**
259
     * Get the bound class (self) for the interactive shell.
260
     *
261
     * @return string|null
262
     */
263
    public function getBoundClass()
264
    {
265
        return $this->boundClass;
266
    }
267
 
268
    /**
269
     * Set command-scope magic variables: $__class, $__file, etc.
270
     *
271
     * @param array $commandScopeVariables
272
     */
273
    public function setCommandScopeVariables(array $commandScopeVariables)
274
    {
275
        $vars = [];
276
        foreach ($commandScopeVariables as $key => $value) {
277
            // kind of type check
278
            if (\is_scalar($value) && \in_array($key, self::$commandScopeNames)) {
279
                $vars[$key] = $value;
280
            }
281
        }
282
 
283
        $this->commandScopeVariables = $vars;
284
    }
285
 
286
    /**
287
     * Get command-scope magic variables: $__class, $__file, etc.
288
     *
289
     * @return array
290
     */
291
    public function getCommandScopeVariables(): array
292
    {
293
        return $this->commandScopeVariables;
294
    }
295
 
296
    /**
297
     * Get unused command-scope magic variables names: __class, __file, etc.
298
     *
299
     * This is used by the shell to unset old command-scope variables after a
300
     * new batch is set.
301
     *
302
     * @return array Array of unused variable names
303
     */
304
    public function getUnusedCommandScopeVariableNames(): array
305
    {
306
        return \array_diff(self::$commandScopeNames, \array_keys($this->commandScopeVariables));
307
    }
308
 
309
    /**
310
     * Check whether a variable name is a magic variable.
311
     *
312
     * @param string $name
313
     *
314
     * @return bool
315
     */
316
    public static function isSpecialVariableName(string $name): bool
317
    {
318
        return \in_array($name, self::$specialNames) || \in_array($name, self::$commandScopeNames);
319
    }
320
}