Completed
Push — master ( f42a52...0a9499 )
by Thierry
02:50 queued 01:16
created

CallableFunction   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
dl 0
loc 190
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 3
A getName() 0 4 1
A getTarget() 0 8 2
B register() 0 49 8
A generateHash() 0 4 1
A getScript() 0 11 2
A canProcessRequest() 0 9 3
A processRequest() 0 25 4
1
<?php
2
3
/**
4
 * CallableFunction.php - Jaxon user function plugin
5
 *
6
 * This class registers user defined functions, generates client side javascript code,
7
 * and calls them on user request
8
 *
9
 * @package jaxon-core
10
 * @author Jared White
11
 * @author J. Max Wilson
12
 * @author Joseph Woolley
13
 * @author Steffen Konerow
14
 * @author Thierry Feuzeu <[email protected]>
15
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
16
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
17
 * @copyright 2016 Thierry Feuzeu <[email protected]>
18
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
19
 * @link https://github.com/jaxon-php/jaxon-core
20
 */
21
22
namespace Jaxon\Request\Plugin;
23
24
use Jaxon\Jaxon;
25
use Jaxon\Plugin\Request as RequestPlugin;
26
use Jaxon\Request\Target;
27
28
class CallableFunction extends RequestPlugin
29
{
30
    use \Jaxon\Features\Validator;
31
    use \Jaxon\Features\Translator;
32
33
    /**
34
     * The registered user functions names
35
     *
36
     * @var array
37
     */
38
    protected $aFunctions = [];
39
40
    /**
41
     * The name of the function that is being requested (during the request processing phase)
42
     *
43
     * @var string
44
     */
45
    protected $sRequestedFunction = null;
46
47
    /**
48
     * The constructor
49
     */
50
    public function __construct()
51
    {
52
        if(isset($_GET['jxnfun']))
53
        {
54
            $this->sRequestedFunction = $_GET['jxnfun'];
55
        }
56
        if(isset($_POST['jxnfun']))
57
        {
58
            $this->sRequestedFunction = $_POST['jxnfun'];
59
        }
60
    }
61
62
    /**
63
     * Return the name of this plugin
64
     *
65
     * @return string
66
     */
67
    public function getName()
68
    {
69
        return Jaxon::CALLABLE_FUNCTION;
70
    }
71
72
    /**
73
     * Return the target function
74
     *
75
     * @return Target|null
76
     */
77
    public function getTarget()
78
    {
79
        if(!$this->sRequestedFunction)
80
        {
81
            return null;
82
        }
83
        return Target::makeFunction($this->sRequestedFunction);
84
    }
85
86
    /**
87
     * Register a user defined function
88
     *
89
     * @param string        $sType          The type of request handler being registered
90
     * @param string        $sCallableFunction  The name of the function being registered
91
     * @param array|string  $aOptions       The associated options
92
     *
93
     * @return \Jaxon\Request\Request
94
     */
95
    public function register($sType, $sCallableFunction, $aOptions)
96
    {
97
        $sType = trim($sType);
98
        if($sType != $this->getName())
99
        {
100
            return false;
101
        }
102
103
        if(!is_string($sCallableFunction))
104
        {
105
            throw new \Jaxon\Exception\Error($this->trans('errors.functions.invalid-declaration'));
106
        }
107
108
        if(is_string($aOptions))
109
        {
110
            $aOptions = ['include' => $aOptions];
111
        }
112
        if(!is_array($aOptions))
113
        {
114
            throw new \Jaxon\Exception\Error($this->trans('errors.functions.invalid-declaration'));
115
        }
116
117
        $sCallableFunction = trim($sCallableFunction);
118
        // Check if an alias is defined
119
        $sFunctionName = $sCallableFunction;
120
        foreach($aOptions as $sName => $sValue)
121
        {
122
            if($sName == 'alias')
123
            {
124
                $sFunctionName = $sValue;
125
                break;
126
            }
127
        }
128
129
        $this->aFunctions[$sFunctionName] = $aOptions;
130
        jaxon()->di()->set($sFunctionName, function () use ($sFunctionName, $sCallableFunction) {
0 ignored issues
show
Documentation introduced by
function () use($sFuncti...n $xCallableFunction; } is of type object<Closure>, but the function expects a object<Jaxon\Utils\DI\Closure>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
131
            $xCallableFunction = new \Jaxon\Request\Support\CallableFunction($sCallableFunction);
132
133
            $aOptions = $this->aFunctions[$sFunctionName];
134
            foreach($aOptions as $sName => $sValue)
135
            {
136
                $xCallableFunction->configure($sName, $sValue);
137
            }
138
139
            return $xCallableFunction;
140
        });
141
142
        return true;
143
    }
144
145
    /**
146
     * Generate a hash for the registered user functions
147
     *
148
     * @return string
149
     */
150
    public function generateHash()
151
    {
152
        return md5(implode('', $this->aFunctions));
153
    }
154
155
    /**
156
     * Generate client side javascript code for the registered user functions
157
     *
158
     * @return string
159
     */
160
    public function getScript()
161
    {
162
        $di = jaxon()->di();
163
        $code = '';
164
        foreach(array_keys($this->aFunctions) as $sName)
165
        {
166
            $xFunction = $di->get($sName);
167
            $code .= $xFunction->getScript();
168
        }
169
        return $code;
170
    }
171
172
    /**
173
     * Check if this plugin can process the incoming Jaxon request
174
     *
175
     * @return boolean
176
     */
177
    public function canProcessRequest()
178
    {
179
        // Check the validity of the function name
180
        if(($this->sRequestedFunction) && !$this->validateFunction($this->sRequestedFunction))
181
        {
182
            $this->sRequestedFunction = null;
183
        }
184
        return ($this->sRequestedFunction != null);
185
    }
186
187
    /**
188
     * Process the incoming Jaxon request
189
     *
190
     * @return boolean
191
     */
192
    public function processRequest()
193
    {
194
        if(!$this->canProcessRequest())
195
        {
196
            return false;
197
        }
198
199
        // Security check: make sure the requested function was registered.
200
        if(!key_exists($this->sRequestedFunction, $this->aFunctions))
201
        {
202
            // Unable to find the requested function
203
            throw new \Jaxon\Exception\Error($this->trans('errors.functions.invalid',
204
                ['name' => $this->sRequestedFunction]));
205
        }
206
207
        $di = jaxon()->di();
208
        $xFunction = $di->get($this->sRequestedFunction);
209
        $aArgs = $di->getRequestHandler()->processArguments();
210
        $xResponse = $xFunction->call($aArgs);
211
        if(($xResponse))
212
        {
213
            $di->getResponseManager()->append($xResponse);
214
        }
215
        return true;
216
    }
217
}
218