private function generateMagicCall($definition)
{
$methods = $definition->methods();
$callName = $methods->methodName('__call');
$methods = $methods->publicMethods();
if (!$callName) {
return '';
}
$methodReflector = $methods[$callName]->method();
$returnsReference = $methodReflector->returnsReference() ? '&' : '';
$source = <<<EOD
public function {$returnsReference}__call(
EOD;
$signature = $this->signatureInspector->signature($methodReflector);
$index = -1;
foreach ($signature as $parameter) {
if (-1 !== $index) {
$source .= ',';
}
$source .= "\n " . $parameter[0] . $parameter[1] . '$a' . ++$index . $parameter[2];
}
if ($this->isReturnTypeSupported && $methodReflector->hasReturnType()) {
$type = $methodReflector->getReturnType();
$isBuiltin = $type->isBuiltin();
if ($this->isHhvm) {
// @codeCoverageIgnoreStart
$typeString = $methodReflector->getReturnTypeText();
// TODO: review HHVM usage of ? prefix
if (0 === strpos($typeString, '?')) {
$typeString = '';
} else {
$genericPosition = strpos($typeString, '<');
if (false !== $genericPosition) {
$typeString = substr($typeString, 0, $genericPosition);
}
}
$isBuiltin = $isBuiltin && false === strpos($typeString, '\\');
// @codeCoverageIgnoreEnd
} else {
if ($type->allowsNull()) {
$typeString = '?' . $type;
// @codeCoverageIgnore
} else {
$typeString = (string) $type;
}
}
if ('self' === $typeString) {
$typeString = $methodReflector->getDeclaringClass()->getName();
}
if ($isBuiltin) {
$source .= "\n ) : " . $typeString . " {\n";
// TODO: remove once PHP 7.1 is used for coverage
// @codeCoverageIgnoreStart
} elseif ($this->isNullableTypeSupported && 0 === strpos($typeString, '?')) {
$source .= "\n ) : ?\\" . substr($typeString, 1) . " {\n";
// @codeCoverageIgnoreEnd
} else {
$source .= "\n ) : \\" . $typeString . " {\n";
}
$isVoidReturn = $isBuiltin && 'void' === $typeString;
} else {
$source .= "\n ) {\n";
$isVoidReturn = false;
}
// TODO: remove once PHP 7.1 is used for coverage
// @codeCoverageIgnoreStart
if ($isVoidReturn) {
$source .= <<<'EOD'
$this->_handle->spy($a0)
->invokeWith(new \Eloquent\Phony\Call\Arguments($a1));
}
EOD;
} else {
// @codeCoverageIgnoreEnd
$source .= <<<'EOD'
$result = $this->_handle->spy($a0)
->invokeWith(new \Eloquent\Phony\Call\Arguments($a1));
return $result;
}
EOD;
}
return $source;
}