MethodInvocation::injectThrownException()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * \AppserverIo\Doppelgaenger\Entities\MethodInvocation
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Bernhard Wick <[email protected]>
15
 * @copyright 2015 TechDivision GmbH - <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/doppelgaenger
18
 * @link      http://www.appserver.io/
19
 */
20
21
namespace AppserverIo\Doppelgaenger\Entities;
22
23
use AppserverIo\Psr\MetaobjectProtocol\Aop\MethodInvocationInterface;
24
25
/**
26
 * DTO which will be used to represent an invoked method and will therefor hold information about it as well as the
27
 * functionality to invoke the initially called logic
28
 *
29
 * @author    Bernhard Wick <[email protected]>
30
 * @copyright 2015 TechDivision GmbH - <[email protected]>
31
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
32
 * @link      https://github.com/appserver-io/doppelgaenger
33
 * @link      http://www.appserver.io/
34
 */
35
class MethodInvocation implements MethodInvocationInterface
36
{
37
38
    /**
39
     * Array containing callbacks which allow to call the contained piece of code.
40
     * Allows for a chain of callbacks e.g. with advice chaining
41
     *
42
     * @var array<callable> $callbackChain
43
     */
44
    protected $callbackChain;
45
46
    /**
47
     * The context in which the invocation happens, is the same as accessing $this within the method logic
48
     *
49
     * @var object $context
50
     */
51
    protected $context;
52
53
    /**
54
     * Is the function abstract?
55
     *
56
     * @var boolean $isAbstract
57
     */
58
    protected $isAbstract;
59
60
    /**
61
     * Is the function final?
62
     *
63
     * @var boolean $isFinal
64
     */
65
    protected $isFinal;
66
67
    /**
68
     * Is the method static?
69
     *
70
     * @var boolean $isStatic
71
     */
72
    protected $isStatic;
73
74
    /**
75
     * The name of the function
76
     *
77
     * @var string $name
78
     */
79
    protected $name;
80
81
    /**
82
     * Array of parameters of the form <PARAMETER_NAME> => <PARAMETER_VALUE>
83
     *
84
     * @var array $parameters
85
     */
86
    protected $parameters;
87
88
    /**
89
     * The result of the method invocation
90
     *
91
     * @var mixed $result
92
     */
93
    protected $result;
94
95
    /**
96
     * Name of the structure (class/trait/...) which contains the method
97
     *
98
     * @var string $structureName
99
     */
100
    protected $structureName;
101
102
    /**
103
     * The exception thrown by the method invocation
104
     *
105
     * @var \Exception $thrownException
106
     */
107
    protected $thrownException;
108
109
    /**
110
     * Visibility of the method
111
     *
112
     * @var string $visibility
113
     */
114
    protected $visibility;
115
116
    /**
117
     * Default constructor
118
     *
119
     * @param array<callable> $callbackChain Callback which allows to call the initially invoked
120
     * @param object          $context       The context in which the invocation happens e.g. $this
121
     * @param boolean         $isAbstract    Is the function abstract?
122
     * @param boolean         $isFinal       Is the function final?
123
     * @param boolean         $isStatic      Is the method static?
124
     * @param string          $name          The name of the function
125
     * @param array           $parameters    Array of parameters of the form <PARAMETER_NAME> => <PARAMETER_VALUE>
126
     * @param string          $structureName Name of the structure (class/trait/...) which contains the method
127
     * @param string          $visibility    Visibility of the method
128
     */
129
    public function __construct(
130
        $callbackChain,
131
        $context,
132
        $isAbstract,
133
        $isFinal,
134
        $isStatic,
135
        $name,
136
        array $parameters,
137
        $structureName,
138
        $visibility
139
    ) {
140
        $this->callbackChain = $callbackChain;
141
        $this->context = $context;
142
        $this->isAbstract = $isAbstract;
143
        $this->isFinal = $isFinal;
144
        $this->isStatic = $isStatic;
145
        $this->name = $name;
146
        $this->parameters = $parameters;
147
        $this->structureName = $structureName;
148
        $this->visibility = $visibility;
149
    }
150
151
    /**
152
     * Getter method for property $context
153
     *
154
     * @return object
155
     */
156
    public function getContext()
157
    {
158
        return $this->context;
159
    }
160
161
    /**
162
     * Getter method for property $name
163
     *
164
     * @return string
165
     */
166
    public function getName()
167
    {
168
        return $this->name;
169
    }
170
171
    /**
172
     * Getter for the result of the method invocation
173
     *
174
     * @return mixed
175
     */
176
    public function getResult()
177
    {
178
        return $this->result;
179
    }
180
181
    /**
182
     * Getter method for property $parameters
183
     *
184
     * @return array
185
     */
186
    public function getParameters()
187
    {
188
        return $this->parameters;
189
    }
190
191
    /**
192
     * Getter method for property $structureName
193
     *
194
     * @return string
195
     */
196
    public function getStructureName()
197
    {
198
        return $this->structureName;
199
    }
200
201
    /**
202
     * Getter method for property $thrownException
203
     *
204
     * @return string
205
     */
206
    public function getThrownException()
207
    {
208
        return $this->thrownException;
209
    }
210
211
    /**
212
     * Getter method for property $visibility
213
     *
214
     * @return string
215
     */
216
    public function getVisibility()
217
    {
218
        return $this->visibility;
219
    }
220
221
    /**
222
     * Will be used to inject the result of the original method
223
     *
224
     * @param mixed $result The result to inject
225
     *
226
     * @return mixed
227
     */
228
    public function injectResult($result)
229
    {
230
        $this->result = $result;
231
    }
232
233
    /**
234
     * Used to injection the thrown exception, if any
235
     *
236
     * @param \Exception $thrownException The exception instance to inject
237
     *
238
     * @return null
239
     */
240
    public function injectThrownException(\Exception $thrownException)
241
    {
242
        $this->thrownException = $thrownException;
243
    }
244
245
    /**
246
     * Getter method for property $isAbstract
247
     *
248
     * @return boolean
249
     */
250
    public function isAbstract()
251
    {
252
        return $this->isAbstract;
253
    }
254
255
    /**
256
     * Getter method for property $isFinal
257
     *
258
     * @return boolean
259
     */
260
    public function isFinal()
261
    {
262
        return $this->isFinal;
263
    }
264
265
    /**
266
     * Getter method for property $isStatic
267
     *
268
     * @return boolean
269
     */
270
    public function isStatic()
271
    {
272
        return $this->isStatic;
273
    }
274
275
    /**
276
     * Will begin the execution of the initially invoked method.
277
     * Acts as a wrapper around the initial method logic and will return the same result and throw the same exceptions,
278
     * so use it instead of the original call
279
     *
280
     * @return mixed
281
     *
282
     * @throws \Exception
283
     */
284
    public function proceed()
285
    {
286
        // if the callback chain is empty we got a real problem, only thing we can do is trying to invoke the original
287
        // implementation.
288
        // but lets throw a warning so the user knows
289
        if (empty($this->callbackChain)) {
290
            trigger_error(
291
                'The callback chain for ' . $this->getStructureName() . '::' . $this->getName() . ' was empty, invoking original implementation.',
292
                E_USER_NOTICE
293
            );
294
            $this->callbackChain = array(
295
                array($this->getContext(), $this->getName())
296
            );
297
        }
298
299
        // get the first entry of the callback and remove it as we don't want to call methods twice
300
        $callback = reset($this->callbackChain);
301
        unset($this->callbackChain[key($this->callbackChain)]);
302
303
        try {
304
            // pass over the method invocation object (instead of original params) as long as we got something in the chain
305
            if (!empty($this->callbackChain)) {
306
                $this->result = call_user_func_array($callback, array($this));
307
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
308
            } else {
309
                $this->result = call_user_func_array($callback, $this->getParameters());
310
            }
311
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
312
        } catch (\Exception $e) {
313
            $this->thrownException = $e;
314
            throw $e;
315
        }
316
317
        return $this->result;
318
    }
319
320
    /**
321
     * Setter method for property $parameters
322
     *
323
     * @param array $parameters New parameters to set
324
     *
325
     * @return null
326
     */
327
    public function setParameters(array $parameters)
328
    {
329
        $this->parameters = $parameters;
330
    }
331
}
332