Skip to content

Commit d6e03a7

Browse files
committed
Merge pull request #131 from Danack/improve_exception_messages
Improve exception messages for invalid callables
2 parents bfaf427 + 5ca20b2 commit d6e03a7

File tree

3 files changed

+84
-26
lines changed

3 files changed

+84
-26
lines changed

lib/InjectionException.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,47 @@ public function __construct(array $inProgressMakes, $message = "", $code = 0, \E
1414
parent::__construct($message, $code, $previous);
1515
}
1616

17+
/**
18+
* Add a human readable version of the invalid callable to the standard 'invalid invokable' message.
19+
*/
20+
public static function fromInvalidCallable(
21+
array $inProgressMakes,
22+
$callableOrMethodStr,
23+
\Exception $previous = null
24+
) {
25+
$callableString = null;
26+
27+
if (is_string($callableOrMethodStr)) {
28+
$callableString .= $callableOrMethodStr;
29+
} else if (is_array($callableOrMethodStr) &&
30+
array_key_exists(0, $callableOrMethodStr) &&
31+
array_key_exists(0, $callableOrMethodStr)) {
32+
if (is_string($callableOrMethodStr[0]) && is_string($callableOrMethodStr[1])) {
33+
$callableString .= $callableOrMethodStr[0].'::'.$callableOrMethodStr[1];
34+
} else if (is_object($callableOrMethodStr[0]) && is_string($callableOrMethodStr[1])) {
35+
$callableString .= sprintf(
36+
"[object(%s), '%s']",
37+
get_class($callableOrMethodStr[0]),
38+
$callableOrMethodStr[1]
39+
);
40+
}
41+
}
42+
43+
if ($callableString) {
44+
// Prevent accidental usage of long strings from filling logs.
45+
$callableString = substr($callableString, 0, 250);
46+
$message = sprintf(
47+
"%s. Invalid callable was '%s'",
48+
Injector::M_INVOKABLE,
49+
$callableString
50+
);
51+
} else {
52+
$message = \Auryn\Injector::M_INVOKABLE;
53+
}
54+
55+
return new self($inProgressMakes, $message, Injector::E_INVOKABLE, $previous);
56+
}
57+
1758
/**
1859
* Returns the hierarchy of dependencies that were being created when
1960
* the exception occurred.

lib/Injector.php

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ private function shareInstance($obj)
222222
public function prepare($name, $callableOrMethodStr)
223223
{
224224
if ($this->isExecutable($callableOrMethodStr) === false) {
225-
throw new InjectionException(
225+
throw InjectionException::fromInvalidCallable(
226226
$this->inProgressMakes,
227-
self::M_INVOKABLE,
228-
self::E_INVOKABLE
227+
self::E_INVOKABLE,
228+
$callableOrMethodStr
229229
);
230230
}
231231

@@ -496,10 +496,9 @@ private function buildArgFromParamDefineArr($definition)
496496
private function buildArgFromDelegate($paramName, $callableOrMethodStr)
497497
{
498498
if ($this->isExecutable($callableOrMethodStr) === false) {
499-
throw new InjectionException(
499+
throw InjectionException::fromInvalidCallable(
500500
$this->inProgressMakes,
501-
self::M_INVOKABLE,
502-
self::E_INVOKABLE
501+
$callableOrMethodStr
503502
);
504503
}
505504

@@ -631,7 +630,15 @@ public function execute($callableOrMethodStr, array $args = array())
631630
*/
632631
public function buildExecutable($callableOrMethodStr)
633632
{
634-
list($reflFunc, $invocationObj) = $this->buildExecutableStruct($callableOrMethodStr);
633+
try {
634+
list($reflFunc, $invocationObj) = $this->buildExecutableStruct($callableOrMethodStr);
635+
} catch (\ReflectionException $e) {
636+
throw InjectionException::fromInvalidCallable(
637+
$this->inProgressMakes,
638+
$callableOrMethodStr,
639+
$e
640+
);
641+
}
635642

636643
return new Executable($reflFunc, $invocationObj);
637644
}
@@ -653,10 +660,9 @@ private function buildExecutableStruct($callableOrMethodStr)
653660
) {
654661
$executableStruct = $this->buildExecutableStructFromArray($callableOrMethodStr);
655662
} else {
656-
throw new InjectionException(
663+
throw InjectionException::fromInvalidCallable(
657664
$this->inProgressMakes,
658-
self::M_INVOKABLE,
659-
self::E_INVOKABLE
665+
$callableOrMethodStr
660666
);
661667
}
662668

@@ -676,10 +682,9 @@ private function buildExecutableStructFromString($stringExecutable)
676682
list($class, $method) = explode('::', $stringExecutable, 2);
677683
$executableStruct = $this->buildStringClassMethodCallable($class, $method);
678684
} else {
679-
throw new InjectionException(
685+
throw InjectionException::fromInvalidCallable(
680686
$this->inProgressMakes,
681-
self::M_INVOKABLE,
682-
self::E_INVOKABLE
687+
$stringExecutable
683688
);
684689
}
685690

@@ -722,10 +727,9 @@ private function buildExecutableStructFromArray($arrayExecutable)
722727
} elseif (is_string($classOrObj)) {
723728
$executableStruct = $this->buildStringClassMethodCallable($classOrObj, $method);
724729
} else {
725-
throw new InjectionException(
730+
throw InjectionException::fromInvalidCallable(
726731
$this->inProgressMakes,
727-
self::M_INVOKABLE,
728-
self::E_INVOKABLE
732+
$arrayExecutable
729733
);
730734
}
731735

test/InjectorTest.php

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -807,25 +807,38 @@ public function testAppropriateExceptionThrownOnNonPublicConstructorWithArgs()
807807
$injector->make('Auryn\Test\HasNonPublicConstructorWithArgs');
808808
}
809809

810-
/**
811-
* @expectedException \Auryn\InjectionException
812-
* @expectedExceptionCode \Auryn\Injector::E_INVOKABLE
813-
*/
814810
public function testMakeExecutableFailsOnNonExistentFunction()
815811
{
816812
$injector = new Injector();
813+
$this->setExpectedException(
814+
'Auryn\InjectionException',
815+
'nonExistentFunction',
816+
\Auryn\Injector::E_INVOKABLE
817+
);
817818
$injector->buildExecutable('nonExistentFunction');
818819
}
819820

820-
/**
821-
* @expectedException \Auryn\InjectionException
822-
* @expectedExceptionCode \Auryn\Injector::E_INVOKABLE
823-
*/
824-
public function testMakeExecutableFailsOnNonExistentMethod()
821+
public function testMakeExecutableFailsOnNonExistentInstanceMethod()
825822
{
826823
$injector = new Injector();
827824
$object = new \StdClass();
828-
$injector->buildExecutable(array($object, 'nonExistentFunction'));
825+
$this->setExpectedException(
826+
'Auryn\InjectionException',
827+
"[object(stdClass), 'nonExistentMethod']",
828+
\Auryn\Injector::E_INVOKABLE
829+
);
830+
$injector->buildExecutable(array($object, 'nonExistentMethod'));
831+
}
832+
833+
public function testMakeExecutableFailsOnNonExistentStaticMethod()
834+
{
835+
$injector = new Injector();
836+
$this->setExpectedException(
837+
'Auryn\InjectionException',
838+
"StdClass::nonExistentMethod",
839+
\Auryn\Injector::E_INVOKABLE
840+
);
841+
$injector->buildExecutable(array('StdClass', 'nonExistentMethod'));
829842
}
830843

831844
/**

0 commit comments

Comments
 (0)