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 894f204 commit 44c5dbf
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 41 deletions.
4 changes: 2 additions & 2 deletions src/Application/LinkGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public function link($dest, array $params = [])
if ($action === '') {
$action = UI\Presenter::DEFAULT_ACTION;
}
if ($params && (method_exists($class, $method = $class::formatActionMethod($action))
|| method_exists($class, $method = $class::formatRenderMethod($action)))
if (method_exists($class, $method = $class::formatActionMethod($action))
|| method_exists($class, $method = $class::formatRenderMethod($action))
) {
UI\Presenter::argsToParams($class, $method, $params);
}
Expand Down
63 changes: 27 additions & 36 deletions src/Application/UI/Presenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -873,9 +873,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 @@ -901,28 +900,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 @@ -1015,7 +1013,9 @@ public static function argsToParams($class, $method, & $args, $supplemental = []
$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 @@ -1026,16 +1026,15 @@ public static function argsToParams($class, $method, & $args, $supplemental = []

} 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 @@ -1046,22 +1045,14 @@ public static function argsToParams($class, $method, & $args, $supplemental = []
));
}

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 && $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
6 changes: 3 additions & 3 deletions tests/UI/Presenter.link().php7.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,10 @@ class TestPresenter extends Application\UI\Presenter
Assert::same('/index.php?int=0&bool=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&bool=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('#error: Argument $int passed to TestPresenter::actionHints() must be int, stdClass given.', $this->link('hints', ['int' => new stdClass]));
Assert::same('#error: Argument $int passed to TestPresenter::actionHints() must be int, array given.', $this->link('hints', ['int' => []]));
Expand Down

0 comments on commit 44c5dbf

Please sign in to comment.