Completed
Push — master ( 84dbb5...744962 )
by Thierry
01:43
created

CallableObject::configure()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 6
nop 2
dl 0
loc 26
rs 8.5706
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * CallableObject.php - Jaxon callable object
5
 *
6
 * This class stores a reference to an object whose methods can be called from
7
 * the client via an Jaxon request
8
 *
9
 * The Jaxon plugin manager will call <CallableObject->getClientScript> so that
10
 * stub functions can be generated and sent to the browser.
11
 *
12
 * @package jaxon-core
13
 * @author Jared White
14
 * @author J. Max Wilson
15
 * @author Joseph Woolley
16
 * @author Steffen Konerow
17
 * @author Thierry Feuzeu <[email protected]>
18
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
19
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
20
 * @copyright 2016 Thierry Feuzeu <[email protected]>
21
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
22
 * @link https://github.com/jaxon-php/jaxon-core
23
 */
24
25
namespace Jaxon\Request\Support;
26
27
use Jaxon\Request\Request;
28
29
class CallableObject
30
{
31
    /**
32
     * A reference to the callable object the user has registered
33
     *
34
     * @var object
35
     */
36
    private $registeredObject = null;
37
38
    /**
39
     * The reflection class of the user registered callable object
40
     *
41
     * @var \ReflectionClass
42
     */
43
    private $reflectionClass;
44
45
    /**
46
     * A list of methods of the user registered callable object the library must not export to javascript
47
     *
48
     * @var array
49
     */
50
    private $aProtectedMethods = [];
51
52
    /**
53
     * The character to use as separator in javascript class names
54
     *
55
     * @var string
56
     */
57
    private $separator = '.';
58
59
    /**
60
     * The class constructor
61
     *
62
     * @param string            $sCallable               The callable object instance or class name
63
     *
64
     */
65
    public function __construct($sCallable)
66
    {
67
        $this->reflectionClass = new \ReflectionClass($sCallable);
68
    }
69
70
    /**
71
     * Return the class name of this callable object, without the namespace if any
72
     *
73
     * @return string
74
     */
75
    public function getClassName()
76
    {
77
        // Get the class name without the namespace.
78
        return $this->reflectionClass->getShortName();
79
    }
80
81
    /**
82
     * Return the name of this callable object
83
     *
84
     * @return string
85
     */
86
    public function getName()
87
    {
88
        // Get the class name with the namespace.
89
        return $this->reflectionClass->getName();
90
    }
91
92
    /**
93
     * Return the name of the corresponding javascript class
94
     *
95
     * @return string
96
     */
97
    public function getJsName()
98
    {
99
        return str_replace('\\', $this->separator, $this->getName());
100
    }
101
102
    /**
103
     * Return the namespace of this callable object
104
     *
105
     * @return string
106
     */
107
    public function getNamespace()
108
    {
109
        // The namespace the class was registered with.
110
        return $this->reflectionClass->getNamespaceName();
111
    }
112
113
    /**
114
     * Set configuration options / call options for each method
115
     *
116
     * @param string        $sName              The name of the configuration option
117
     * @param string        $sValue             The value of the configuration option
118
     *
119
     * @return void
120
     */
121
    public function configure($sName, $sValue)
122
    {
123
        switch($sName)
124
        {
125
        // Set the separator
126
        case 'separator';
127
            if($sValue == '_' || $sValue == '.')
128
            {
129
                $this->separator = $sValue;
130
            }
131
            break;
132
        // Set the protected methods
133
        case 'protected':
134
            if(is_array($sValue))
135
            {
136
                $this->aProtectedMethods = array_merge($this->aProtectedMethods, $sValue);
137
            }
138
            elseif(is_string($sValue))
139
            {
140
                $this->aProtectedMethods[] = $sValue;
141
            }
142
            break;
143
        default:
144
            break;
145
        }
146
    }
147
148
    /**
149
     * Return a list of methods of the callable object to export to javascript
150
     *
151
     * @return array
152
     */
153
    public function getMethods()
154
    {
155
        $aMethods = [];
156
        foreach($this->reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $xMethod)
157
        {
158
            $sMethodName = $xMethod->getShortName();
159
            // Don't take magic __call, __construct, __destruct methods
160
            if(strlen($sMethodName) > 2 && substr($sMethodName, 0, 2) == '__')
161
            {
162
                continue;
163
            }
164
            // Don't take excluded methods
165
            if(in_array($sMethodName, $this->aProtectedMethods))
166
            {
167
                continue;
168
            }
169
            $aMethods[] = $sMethodName;
170
        }
171
        return $aMethods;
172
    }
173
174
    /**
175
     * Return the registered callable object
176
     *
177
     * @return object
178
     */
179
    public function getRegisteredObject()
180
    {
181
        if($this->registeredObject == null)
182
        {
183
            $di = jaxon()->di();
184
            // Use the Reflection class to get the parameters of the constructor
185
            if(($constructor = $this->reflectionClass->getConstructor()) != null)
186
            {
187
                $parameters = $constructor->getParameters();
188
                $parameterInstances = [];
189
                foreach($parameters as $parameter)
190
                {
191
                    // Get the parameter instance from the DI
192
                    $parameterInstances[] = $di->get($parameter->getClass()->getName());
193
                }
194
                $this->registeredObject = $this->reflectionClass->newInstanceArgs($parameterInstances);
195
            }
196
            else
197
            {
198
                $this->registeredObject = $this->reflectionClass->newInstance();
199
            }
200
        }
201
        return $this->registeredObject;
202
    }
203
204
    /**
205
     * Check if the specified method name is one of the methods of the registered callable object
206
     *
207
     * @param string        $sMethod            The name of the method to check
208
     *
209
     * @return boolean
210
     */
211
    public function hasMethod($sMethod)
212
    {
213
        return $this->reflectionClass->hasMethod($sMethod)/* || $this->reflectionClass->hasMethod('__call')*/;
214
    }
215
216
    /**
217
     * Call the specified method of the registered callable object using the specified array of arguments
218
     *
219
     * @param string        $sMethod            The name of the method to call
220
     * @param array         $aArgs              The arguments to pass to the method
221
     *
222
     * @return void
223
     */
224
    public function call($sMethod, $aArgs)
225
    {
226
        if(!$this->hasMethod($sMethod))
227
        {
228
            return;
229
        }
230
        $reflectionMethod = $this->reflectionClass->getMethod($sMethod);
231
        $registeredObject = $this->getRegisteredObject();
232
        $response = $reflectionMethod->invokeArgs($registeredObject, $aArgs);
233
        if(($response))
234
        {
235
            $this->getResponseManager()->append($response);
0 ignored issues
show
Bug introduced by
The method getResponseManager() does not seem to exist on object<Jaxon\Request\Support\CallableObject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
236
        }
237
    }
238
}
239