Skip to content

Commit

Permalink
Simplify code generated by wrap_php_function; make sure its closure v…
Browse files Browse the repository at this point in the history
…ersion is identical wrt the nr. of parameters received
  • Loading branch information
gggeek committed May 23, 2015
1 parent cba9de3 commit 68237fa
Showing 1 changed file with 37 additions and 36 deletions.
73 changes: 37 additions & 36 deletions src/Wrapper.php
Expand Up @@ -146,6 +146,7 @@ public function xmlrpc_2_php_type($xmlrpcType)
* @todo what to do when the PHP function returns NULL? We are currently returning an empty string value...
* @todo add an option to suppress php warnings in invocation of user function, similar to server debug level 3?
* @todo add a verbatim_object_copy parameter to allow avoiding usage the same obj instance?
* @todo add an option to allow generated function to skip validation of number of parameters, as that is done by the server anyway
*/
public function wrap_php_function($callable, $newFuncName = '', $extraOptions = array())
{
Expand Down Expand Up @@ -193,15 +194,12 @@ public function wrap_php_function($callable, $newFuncName = '', $extraOptions =
$funcSigs = $this->buildMethodSignatures($funcDesc);

if ($buildIt) {
$callable = $this->buildWrapFunctionClosure($callable, $extraOptions, null, null);
$callable = $this->buildWrapFunctionClosure($callable, $extraOptions, $plainFuncName, $funcDesc);
} else {
$newFuncName = $this->newFunctionName($callable, $newFuncName, $extraOptions);
$code = $this->buildWrapFunctionSource($callable, $newFuncName, $extraOptions, $plainFuncName, $funcDesc);
}

/// @todo examine if $paramDocs matches $parsVariations and build array for
/// usage as method signature, plus put together a nice string for docs

$ret = array(
'function' => $callable,
'signature' => $funcSigs['sigs'],
Expand Down Expand Up @@ -410,6 +408,22 @@ protected function buildWrapFunctionClosure($callable, $extraOptions, $plainFunc
$responseClass = $nameSpace.'Response';
$valueClass = $nameSpace.'Value';

// validate number of parameters received
// this should be optional really, as we assume the server does the validation
$minPars = count($funcDesc['params']);
$maxPars = $minPars;
foreach ($funcDesc['params'] as $i => $param) {
if ($param['isoptional']) {
// this particular parameter is optional. We assume later ones are as well
$minPars = $i;
break;
}
}
$numPars = $req->getNumParams();
if ($numPars < $minPars || $numPars > $maxPars) {
return new $responseClass(0, 3, 'Incorrect parameters passed to method');
}

$encoder = new $encoderClass();
$options = array();
if (isset($extraOptions['decode_php_objs']) && $extraOptions['decode_php_objs']) {
Expand Down Expand Up @@ -485,6 +499,8 @@ protected function newFunctionName($callable, $newFuncName, $extraOptions)
* @param string $plainFuncName
* @param array $funcDesc
* @return array
*
* @todo add a nice phpdoc block in the generated source
*/
protected function buildWrapFunctionSource($callable, $newFuncName, $extraOptions, $plainFuncName, $funcDesc)
{
Expand All @@ -494,37 +510,19 @@ protected function buildWrapFunctionSource($callable, $newFuncName, $extraOption
$decodePhpObjects = isset($extraOptions['decode_php_objs']) ? (bool)$extraOptions['decode_php_objs'] : false;
$catchWarnings = isset($extraOptions['suppress_warnings']) && $extraOptions['suppress_warnings'] ? '@' : '';

// build body of new function

$innerCode = "\$encoder = new {$namespace}Encoder();\n";
$i = 0;
$parsVariations = array();
$pars = array();
$pNum = count($funcDesc['params']);
foreach ($funcDesc['params'] as $param) {
/*$name = strtolower($funcDesc['params'][$i]['name']);
if (!isset($funcDesc['paramDocs'][$name])) {
// no param found in phpdoc info matching param definition!
$funcDesc['paramDocs'][$name]['type'] = 'mixed';
}*/

if ($param['isoptional']) {
// this particular parameter is optional. save as valid previous list of parameters
$innerCode .= "if (\$paramcount > $i) {\n";
$parsVariations[] = $pars;
}
$innerCode .= "\$p$i = \$req->getParam($i);\n";
if ($decodePhpObjects) {
$innerCode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = \$encoder->decode(\$p$i, array('decode_php_objs'));\n";
} else {
$innerCode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = \$encoder->decode(\$p$i);\n";
}

$pars[] = "\$p$i";
$pars[] = "\$p[$i]";
$i++;
if ($param['isoptional']) {
$innerCode .= "}\n";
}
if ($i == $pNum) {
// last allowed parameters combination
$parsVariations[] = $pars;
Expand All @@ -535,20 +533,24 @@ protected function buildWrapFunctionSource($callable, $newFuncName, $extraOption
// only known good synopsis = no parameters
$parsVariations[] = array();
$minPars = 0;
$maxPars = 0;
} else {
$minPars = count($parsVariations[0]);
$maxPars = count($parsVariations[count($parsVariations)-1]);
}

if ($minPars) {
// add to code the check for min params number
// NB: this check needs to be done BEFORE decoding param values
$innerCode = "\$paramcount = \$req->getNumParams();\n" .
"if (\$paramcount < $minPars) return new {$namespace}Response(0, " . PhpXmlRpc::$xmlrpcerr['incorrect_params'] . ", '" . PhpXmlRpc::$xmlrpcstr['incorrect_params'] . "');\n" . $innerCode;
// build body of new function

$innerCode = "\$paramCount = \$req->getNumParams();\n";
$innerCode .= "if (\$paramCount < $minPars || \$paramCount > $maxPars) return new {$namespace}Response(0, " . PhpXmlRpc::$xmlrpcerr['incorrect_params'] . ", '" . PhpXmlRpc::$xmlrpcstr['incorrect_params'] . "');\n";

$innerCode .= "\$encoder = new {$namespace}Encoder();\n";
if ($decodePhpObjects) {
$innerCode .= "\$p = \$encoder->decode(\$req, array('decode_php_objs'));\n";
} else {
$innerCode = "\$paramcount = \$req->getNumParams();\n" . $innerCode;
$innerCode .= "\$p = \$encoder->decode(\$req);\n";
}

$innerCode .= "\$np = false;\n";
// since we are building source code for later use, if we are given an object instance,
// we go out of our way and store a pointer to it in a static class var var...
if (is_array($callable) && is_object($callable[0])) {
Expand All @@ -558,12 +560,11 @@ protected function buildWrapFunctionSource($callable, $newFuncName, $extraOption
} else {
$realFuncName = $plainFuncName;
}
foreach ($parsVariations as $pars) {
$innerCode .= "if (\$paramcount == " . count($pars) . ") \$retval = {$catchWarnings}$realFuncName(" . implode(',', $pars) . "); else\n";
foreach ($parsVariations as $i => $pars) {
$innerCode .= "if (\$paramCount == " . count($pars) . ") \$retval = {$catchWarnings}$realFuncName(" . implode(',', $pars) . ");\n";
if ($i < (count($parsVariations) - 1))
$innerCode .= "else\n";
}
$innerCode .= "\$np = true;\n";
$innerCode .= "if (\$np) return new {$namespace}Response(0, " . PhpXmlRpc::$xmlrpcerr['incorrect_params'] . ", '" . PhpXmlRpc::$xmlrpcstr['incorrect_params'] . "'); else {\n";
//$innerCode .= "if (\$_xmlrpcs_error_occurred) return new Response(0, $GLOBALS['xmlrpcerr']user, \$_xmlrpcs_error_occurred); else\n";
$innerCode .= "if (is_a(\$retval, '{$namespace}Response')) return \$retval; else\n";
if ($funcDesc['returns'] == Value::$xmlrpcDateTime || $funcDesc['returns'] == Value::$xmlrpcBase64) {
$innerCode .= "return new {$namespace}Response(new {$namespace}Value(\$retval, '{$funcDesc['returns']}'));";
Expand All @@ -578,7 +579,7 @@ protected function buildWrapFunctionSource($callable, $newFuncName, $extraOption
// if($func->returnsReference())
// return false;

$code = "function $newFuncName(\$req) {\n" . $innerCode . "}\n}";
$code = "function $newFuncName(\$req) {\n" . $innerCode . "\n}";

return $code;
}
Expand Down

0 comments on commit 68237fa

Please sign in to comment.