3
3
4
4
class FunctionInjector
5
5
{
6
- protected $ template = <<<EOF
6
+ protected $ template = <<<EOF
7
7
<?php
8
8
namespace {{ns}};
9
9
if (!function_exists('{{ns}}\{{func}}')) {
10
- function {{func}}() {
11
- if (( \$__am_res = __amock_before_func('{{ns}}','{{func}}', func_get_args())) !== __AM_CONTINUE__) {
12
- return \$__am_res;
10
+ function {{func}}() {
11
+ if (( \$__am_res = __amock_before_func('{{ns}}','{{func}}', func_get_args())) !== __AM_CONTINUE__) {
12
+ return \$__am_res;
13
+ }
14
+ return call_user_func_array('{{func}}', func_get_args());
13
15
}
14
- return call_user_func_array('{{func}}', func_get_args());
15
16
}
17
+ EOF ;
18
+
19
+ protected $ templateByRefOptional = <<<EOF
20
+ <?php
21
+ namespace {{ns}};
22
+ if (!function_exists('{{ns}}\{{func}}')) {
23
+ function {{func}}({{arguments}}) {
24
+ \$args = [];
25
+ switch(count(func_get_args())) {
26
+ {{code}} }
27
+ if (( \$__am_res = __amock_before_func('{{ns}}','{{func}}', \$args)) !== __AM_CONTINUE__) {
28
+ return \$__am_res;
29
+ }
30
+ return call_user_func_array('{{func}}', \$args);
31
+ }
16
32
}
17
33
EOF ;
18
- protected $ namespace ;
19
- protected $ function ;
20
- protected $ fileName ;
21
34
22
- function __construct ($ namespace , $ function )
23
- {
24
- $ this ->namespace = $ namespace ;
25
- $ this ->function = $ function ;
26
- $ this ->place ('ns ' , $ this ->namespace );
27
- $ this ->place ('func ' , $ this ->function );
35
+ protected $ namespace ;
28
36
29
- }
37
+ protected $ function ;
38
+ protected $ fileName ;
30
39
31
- public function save ()
32
- {
33
- $ this ->fileName = tempnam (sys_get_temp_dir (), $ this ->function );
34
- file_put_contents ($ this ->fileName , $ this ->template );
35
- }
40
+ function __construct ($ namespace , $ function )
41
+ {
42
+ $ this ->namespace = $ namespace ;
43
+ $ this ->function = $ function ;
44
+ $ this ->placeOptionalAndReferenceFunction ($ namespace , $ function );
45
+ $ this ->place ('ns ' , $ this ->namespace );
46
+ $ this ->place ('func ' , $ this ->function );
47
+ }
36
48
37
- public function inject ()
38
- {
39
- require_once $ this ->fileName ;
40
- }
49
+ public function getParameterDeclaration (\ReflectionParameter $ parameter )
50
+ {
51
+ $ text = (string )$ parameter ;
52
+ if (preg_match ('@Parameter\s#[0-9]+\s\[\s<(required|optional)>(.*)(\sor NULL)(.*)\s\]@ ' , $ text , $ match )) {
53
+ $ text = $ match (2 ).$ match [4 ];
54
+ } elseif (preg_match ('@Parameter\s#[0-9]+\s\[\s<(required|optional)>\s(.*)\s\]@ ' , $ text , $ match )) {
55
+ $ text = $ match [2 ];
56
+ } else {
57
+ throw new \Exception ('reflection api changed. adjust code. ' );
58
+ }
59
+ if ($ parameter ->isOptional ()) {
60
+ $ text .= "=NULL " ;
61
+ }
62
+ return $ text ;
63
+ }
41
64
42
- public function getFileName ()
43
- {
44
- return $ this ->fileName ;
45
- }
65
+ public function placeOptionalAndReferenceFunction ($ namespace , $ function )
66
+ {
67
+ $ reflect = new \ReflectionFunction ($ function );
68
+ $ parameters = [];
69
+ $ args = '' ;
70
+ $ byRef = false ;
71
+ $ optionals = false ;
72
+ $ names = [];
73
+ foreach ($ reflect ->getParameters () as $ parameter ) {
74
+ $ name = '$ ' .$ parameter ->getName ();
75
+ $ newname = '$p ' .$ parameter ->getPosition ();
76
+ $ declaration = str_replace ($ name , $ newname , $ this ->getParameterDeclaration ($ parameter ));
77
+ $ name = $ newname ;
78
+ if (!$ optionals && $ parameter ->isOptional ()) {
79
+ $ optionals = true ;
80
+ }
81
+ if ($ parameter ->isPassedByReference ()) {
82
+ $ name = '& ' .$ name ;
83
+ $ byRef = true ;
84
+ }
85
+ $ names [] = $ name ;
86
+ $ parameters [$ newname ] = $ declaration ;
87
+ }
88
+ if ($ optionals || $ byRef ) {
89
+ $ this ->template = $ this ->templateByRefOptional ;
90
+ $ this ->place ('arguments ' , join (', ' , $ parameters ));
91
+ $ code = '' ;
92
+ for ($ i = count ($ parameters ); $ i > 0 ; $ i --) {
93
+ $ code .= " case {$ i }: \$args = [ " . join (', ' , $ names ) . "]; break; \n" ;
94
+ array_pop ($ names );
95
+ }
96
+ $ this ->place ('code ' , $ code );
97
+ }
98
+ }
46
99
47
- public function getPHP ()
48
- {
49
- return $ this ->template ;
50
- }
100
+ public function save ()
101
+ {
102
+ $ this ->fileName = tempnam (sys_get_temp_dir (), $ this ->function );
103
+ file_put_contents ($ this ->fileName , $ this ->template );
104
+ }
51
105
52
- protected function place ($ var , $ value )
53
- {
54
- $ this ->template = str_replace ("{{ {$ var }}} " , $ value , $ this ->template );
55
- }
106
+ public function inject ()
107
+ {
108
+ require_once $ this ->fileName ;
109
+ }
110
+
111
+ public function getFileName ()
112
+ {
113
+ return $ this ->fileName ;
114
+ }
115
+
116
+ public function getPHP ()
117
+ {
118
+ return $ this ->template ;
119
+ }
120
+
121
+ protected function place ($ var , $ value )
122
+ {
123
+ $ this ->template = str_replace ("{{ {$ var }}} " , $ value , $ this ->template );
124
+ }
56
125
}
0 commit comments