1+ <?php
2+
3+ namespace Spamer \DependencyMocker ;
4+
5+ use Nette ;
6+ use Mockery ;
7+
8+ class Mocker
9+ {
10+ /** @var array */
11+ public static $ bannedClasses ;
12+
13+ /** @var \ReflectionClass */
14+ private static $ reflectedClass ;
15+
16+ /** @var Mockery\Mock */
17+ private static $ mockedClass ;
18+
19+ /**
20+ * @param string $className
21+ * @return \ReflectionClass|\stdClass
22+ */
23+ public static function mockClassDependencies ($ className )
24+ {
25+ self ::$ reflectedClass = new \ReflectionClass ($ className );
26+ self ::$ mockedClass = Mockery::mock ($ className );
27+
28+ self ::mockInjectedMethods ($ className );
29+ self ::mockInjectedProperties ();
30+ self ::mockConstructorDependencies ($ className );
31+
32+ return self ::$ mockedClass ;
33+ }
34+
35+
36+ /**
37+ * @param string $className
38+ */
39+ private static function mockInjectedMethods ($ className )
40+ {
41+ foreach (self ::$ reflectedClass ->getMethods () as $ method ) {
42+ if (substr ($ method ->getName (), 0 , 6 ) === 'inject ' ) {
43+ self ::mockDependenciesFromMethod ($ className , $ method ->getName ());
44+ }
45+ }
46+ }
47+
48+
49+ private static function mockInjectedProperties ()
50+ {
51+ /** @var \ReflectionProperty $property */
52+ foreach (self ::$ reflectedClass ->getProperties () as $ property ) {
53+ if (
54+ Nette \DI \PhpReflection::parseAnnotation ($ property , 'inject ' ) !== NULL
55+ ||
56+ Nette \DI \PhpReflection::parseAnnotation ($ property , 'autowire ' ) !== NULL
57+ ) {
58+ if ($ mockedParameterClass = Nette \DI \PhpReflection::parseAnnotation ($ property , 'var ' )) {
59+ $ mockedParameterClass = Nette \DI \PhpReflection::expandClassName (
60+ $ mockedParameterClass ,
61+ Nette \DI \PhpReflection::getDeclaringClass ($ property )
62+ );
63+ }
64+ self ::setProperty ($ mockedParameterClass , $ property );
65+ }
66+ }
67+ }
68+
69+
70+ /**
71+ * @param string $className
72+ */
73+ private static function mockConstructorDependencies ($ className )
74+ {
75+ self ::mockDependenciesFromMethod ($ className , '__construct ' );
76+ }
77+
78+
79+ /**
80+ * @param string $className
81+ * @param string $methodName
82+ */
83+ private static function mockDependenciesFromMethod ($ className , $ methodName )
84+ {
85+ $ reflectionMethod = new \ReflectionMethod ($ className , $ methodName );
86+ $ parameters = $ reflectionMethod ->getParameters ();
87+
88+ /** @var \ReflectionParameter $parameter */
89+ foreach ($ parameters as $ parameter ) {
90+ if ($ parameter ->getClass ()) {
91+ $ parameterClass = $ parameter ->getClass ()->getName ();
92+ self ::setProperty ($ parameterClass , $ parameter );
93+ }
94+ }
95+ }
96+
97+
98+ /**
99+ * @param array $bannedClasses
100+ */
101+ public static function setBannedClasses ($ bannedClasses )
102+ {
103+ self ::$ bannedClasses = $ bannedClasses ;
104+ }
105+
106+
107+ /**
108+ * @param string $className
109+ * @param \ReflectionParameter|\ReflectionProperty $class
110+ */
111+ private static function setProperty ($ className , $ class )
112+ {
113+ if ( ! in_array ($ className , self ::$ bannedClasses ) && $ class ->getDeclaringClass ()->hasProperty ($ class ->getName ())) {
114+ $ mockedParameter = Mockery::mock ($ className );
115+ $ property = new \ReflectionProperty ($ class ->getDeclaringClass ()->getName (), $ class ->getName ());
116+ $ property ->setAccessible (TRUE );
117+ $ property ->setValue (self ::$ mockedClass , $ mockedParameter );
118+ }
119+ }
120+
121+
122+ /**
123+ * @param string $class
124+ * @param string $property
125+ * @param object $object
126+ * @return mixed
127+ */
128+ public static function getProperty ($ class , $ property , $ object )
129+ {
130+ $ property = new \ReflectionProperty ($ class , $ property );
131+ $ property ->setAccessible (TRUE );
132+ return $ property ->getValue ($ object );
133+ }
134+ }
0 commit comments