Skip to content

Commit

Permalink
Presenter: throws exception when parameter has scalar type hint & no …
Browse files Browse the repository at this point in the history
…default value and argument is missing [Closes #112]
  • Loading branch information
dg committed Jan 22, 2016
1 parent dd56e0c commit 1daeee0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 40 deletions.
63 changes: 27 additions & 36 deletions src/Application/UI/Presenter.php
Expand Up @@ -872,9 +872,8 @@ protected function createRequest($component, $destination, array $args, $mode)
if (!$reflection->hasCallableMethod($method)) {
throw new InvalidLinkException("Unknown signal '$signal', missing handler {$reflection->getName()}::$method()");
}
if ($args) { // convert indexed parameters to named
self::argsToParams(get_class($component), $method, $args);
}
// convert indexed parameters to named
self::argsToParams(get_class($component), $method, $args);
}

// counterpart of IStatePersistent
Expand All @@ -900,28 +899,27 @@ protected function createRequest($component, $destination, array $args, $mode)
$current = ($action === '*' || strcasecmp($action, $this->action) === 0) && $presenterClass === get_class($this);

$reflection = new PresenterComponentReflection($presenterClass);
if ($args || $destination === 'this') {
// counterpart of run() & tryCall()
$method = $presenterClass::formatActionMethod($action);

// counterpart of run() & tryCall()
$method = $presenterClass::formatActionMethod($action);
if (!$reflection->hasCallableMethod($method)) {
$method = $presenterClass::formatRenderMethod($action);
if (!$reflection->hasCallableMethod($method)) {
$method = $presenterClass::formatRenderMethod($action);
if (!$reflection->hasCallableMethod($method)) {
$method = NULL;
}
$method = NULL;
}
}

// convert indexed parameters to named
if ($method === NULL) {
if (array_key_exists(0, $args)) {
throw new InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method.");
}
// convert indexed parameters to named
if ($method === NULL) {
if (array_key_exists(0, $args)) {
throw new InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method.");
}

} elseif ($destination === 'this') {
self::argsToParams($presenterClass, $method, $args, $this->params);
} elseif ($destination === 'this') {
self::argsToParams($presenterClass, $method, $args, $this->params);

} else {
self::argsToParams($presenterClass, $method, $args);
}
} else {
self::argsToParams($presenterClass, $method, $args);
}

// counterpart of IStatePersistent
Expand Down Expand Up @@ -1014,7 +1012,9 @@ public static function argsToParams($class, $method, & $args, $supplemental = ar
$i = 0;
$rm = new \ReflectionMethod($class, $method);
foreach ($rm->getParameters() as $param) {
list($type, $isClass) = PresenterComponentReflection::getParameterType($param);
$name = $param->getName();

if (array_key_exists($i, $args)) {
$args[$name] = $args[$i];
unset($args[$i]);
Expand All @@ -1025,16 +1025,15 @@ public static function argsToParams($class, $method, & $args, $supplemental = ar

} elseif (array_key_exists($name, $supplemental)) {
$args[$name] = $supplemental[$name];

} else {
continue;
}

if ($args[$name] === NULL) {
continue;
if (!isset($args[$name])) {
if ($param->isDefaultValueAvailable() || $type === 'NULL' || $type === 'array' || $isClass) {
continue;
}
throw new InvalidLinkException("Missing parameter \$$name required by $class::{$rm->getName()}()");
}

list($type, $isClass) = PresenterComponentReflection::getParameterType($param);
if (!PresenterComponentReflection::convertType($args[$name], $type, $isClass)) {
throw new InvalidLinkException(sprintf(
'Argument $%s passed to %s() must be %s, %s given.',
Expand All @@ -1045,22 +1044,14 @@ public static function argsToParams($class, $method, & $args, $supplemental = ar
));
}

if ($param->isDefaultValueAvailable()) {
$def = $param->getDefaultValue();
} else {
$def = NULL;
if (!$isClass) {
settype($def, $type);
}
}
$def = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : NULL;
if ($args[$name] === $def || ($def === NULL && is_scalar($args[$name]) && (string) $args[$name] === '')) {
$args[$name] = NULL; // value transmit is unnecessary
}
}

if (array_key_exists($i, $args)) {
$method = $rm->getName();
throw new InvalidLinkException("Passed more parameters than method $class::$method() expects.");
throw new InvalidLinkException("Passed more parameters than method $class::{$rm->getName()}() expects.");
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/UI/Presenter.link().php7.phpt
Expand Up @@ -144,12 +144,12 @@ class TestPresenter extends Application\UI\Presenter
Assert::same('/index.php?int=0&action=params&presenter=Test', $this->link('params', ['int' => 0, 'bool' => FALSE, 'str' => '', 'arr' => '']));
Assert::same('/index.php?action=params&presenter=Test', $this->link('params', ['int' => new stdClass]));

Assert::same('/index.php?action=hints&presenter=Test', $this->link('hints', []));
Assert::same('/index.php?action=hints&presenter=Test', $this->link('hints', ['int' => NULL, 'bool' => NULL, 'str' => NULL, 'arr' => NULL]));
Assert::same('#error: Missing parameter $int required by TestPresenter::actionHints()', $this->link('hints', []));
Assert::same('#error: Missing parameter $int required by TestPresenter::actionHints()', $this->link('hints', ['int' => NULL, 'bool' => NULL, 'str' => NULL, 'arr' => NULL]));
Assert::same('/index.php?int=1&bool=1&str=abc&arr%5B0%5D=1&action=hints&presenter=Test', $this->link('hints', ['int' => '1', 'bool' => '1', 'str' => 'abc', 'arr' => [1]]));
Assert::same('/index.php?action=hints&presenter=Test', $this->link('hints', ['int' => 0, 'bool' => FALSE, 'str' => '', 'arr' => []]));
Assert::same('/index.php?int=0&action=hints&presenter=Test', $this->link('hints', ['int' => 0, 'bool' => FALSE, 'str' => '', 'arr' => []]));
Assert::same('#error: Argument $int passed to TestPresenter::actionHints() must be int, string given.', $this->link('hints', ['int' => '']));
Assert::same('/index.php?action=hints&presenter=Test', $this->link('hints', ['int' => new stdClass]));
Assert::same('#error: Missing parameter $bool required by TestPresenter::actionHints()', $this->link('hints', ['int' => new stdClass]));
Assert::same('#error: Argument $int passed to TestPresenter::actionHints() must be int, array given.', $this->link('hints', ['int' => []]));
Assert::same('#error: Argument $bool passed to TestPresenter::actionHints() must be bool, string given.', $this->link('hints', ['int' => '1', 'bool' => '']));
Assert::same('#error: Argument $arr passed to TestPresenter::actionHints() must be array, string given.', $this->link('hints', ['int' => '1', 'bool' => '1', 'str' => '', 'arr' => '']));
Expand Down

0 comments on commit 1daeee0

Please sign in to comment.