mageekguy\atoum\php\mocker: lines coverage

90% of 680

OPs

95% of 99

Lines

70% of 91

Branches

54% of 50

Paths
Method OPs OPs % Lines Line % Branches Branches % Paths Path %
mageekguy\atoum\php\mocker::__construct() 14 100% 4 100% 1 0% 1 100%
mageekguy\atoum\php\mocker::__get() 14 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::__set() 17 100% 2 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::__isset() 16 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::__unset() 15 100% 2 100% 1 0% 1 100%
mageekguy\atoum\php\mocker::setDefaultNamespace() 23 100% 6 100% 4 100% 2 100%
mageekguy\atoum\php\mocker::getDefaultNamespace() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::setReflectedFunctionFactory() 12 100% 2 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::useClassNamespace() 24 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::generate() 96 99% 13 100% 7 86% 3 100%
mageekguy\atoum\php\mocker::resetCalls() 19 100% 2 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::setAdapter() 15 100% 2 100% 1 0% 1 100%
mageekguy\atoum\php\mocker::getAdapter() 7 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::getFqdn() 8 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::generateIfNotExists() 23 100% 5 100% 4 100% 2 100%
mageekguy\atoum\php\mocker::setDefaultBehavior() 74 100% 12 100% 8 88% 4 50%
mageekguy\atoum\php\mocker::functionExists() 11 100% 1 100% 1 100% 1 100%
mageekguy\atoum\php\mocker::getParametersSignature() 94 64% 13 85% 16 56% 8 0%
mageekguy\atoum\php\mocker::getParameters() 50 78% 5 100% 10 50% 4 0%
mageekguy\atoum\php\mocker::getParameterType() 62 69% 10 70% 15 47% 7 0%
mageekguy\atoum\php\mocker::defineMockedFunction() 41 100% 9 100% 9 89% 4 50%
mageekguy\atoum\php\mocker::buildReflectedFunction() 22 100% 4 100% 4 75% 2 100%
mageekguy\atoum\php\mocker::filterParameters() 17 100% 1 100% 1 100% 1 100%
#
1
<?php
2

                    
3
namespace mageekguy\atoum\php;
4

                    
5
use
6
	mageekguy\atoum,
7
	mageekguy\atoum\exceptions
8
;
9

                    
10
class mocker
11
{
12
	protected $defaultNamespace = '';
13
	protected $reflectedFunctionFactory = null;
14

                    
15
	protected static $adapter = null;
16

                    
17
	public function __construct($defaultNamespace = '')100%
18
	{
19
		$this
20
			->setDefaultNamespace($defaultNamespace)
21
			->setReflectedFunctionFactory()
22
		;
23
	}
24

                    
25
	public function __get($functionName)100%
26
	{
27
		return static::$adapter->{$this->generateIfNotExists($functionName)};
28
	}
29

                    
30
	public function __set($functionName, $mixed)100%
31
	{
32
		static::$adapter->{$this->generateIfNotExists($functionName)} = $mixed;
33

                    
34
		return $this;
35
	}
36

                    
37
	public function __isset($functionName)100%
38
	{
39
		return $this->functionExists($this->getFqdn($functionName));
40
	}
41

                    
42
	public function __unset($functionName)100%
43
	{
44
		$this->setDefaultBehavior($this->getFqdn($functionName));
45
	}
46

                    
47
	public function setDefaultNamespace($namespace)100%
48
	{
49
		$this->defaultNamespace = trim($namespace, '\\');
50

                    
51
		if ($this->defaultNamespace !== '')
52
		{
53
			$this->defaultNamespace .= '\\';
54
		}
55

                    
56
		return $this;
57
	}
58

                    
59
	public function getDefaultNamespace()100%
60
	{
61
		return $this->defaultNamespace;
62
	}
63

                    
64
	public function setReflectedFunctionFactory(\closure $factory = null)100%
65
	{
66
		$this->reflectedFunctionFactory = $factory ?: function($functionName) { return new \reflectionFunction($functionName); };
67

                    
68
		return $this;
69
	}
70

                    
71
	public function useClassNamespace($className)100%
72
	{
73
		return $this->setDefaultNamespace(substr($className, 0, strrpos($className, '\\')));
74
	}
75

                    
76
	public function generate($functionName)100%
77
	{
78
		$fqdn = $this->getFqdn($functionName);
79

                    
80
		if ($this->functionExists($fqdn) === false)
81
		{
82
			if (function_exists($fqdn) === true)
83
			{
84
				throw new exceptions\logic\invalidArgument('Function \'' . $fqdn . '\' already exists');
85
			}
86

                    
87
			$lastAntislash = strrpos($fqdn, '\\');
88
			$namespace = substr($fqdn, 0, $lastAntislash);
89
			$function = substr($fqdn, $lastAntislash + 1);
90
			$reflectedFunction = $this->buildReflectedFunction($function);
91

                    
92
			static::defineMockedFunction($namespace, get_class($this), $function, $reflectedFunction);
93
		}
94

                    
95
		return $this->setDefaultBehavior($fqdn);
96
	}
97

                    
98
	public function resetCalls($functionName = null)100%
99
	{
100
		static::$adapter->resetCalls($this->getFqdn($functionName));
101

                    
102
		return $this;
103
	}
104

                    
105
	public static function setAdapter(atoum\test\adapter $adapter = null)100%
106
	{
107
		static::$adapter = $adapter ?: new atoum\php\mocker\adapter();
108
	}
109

                    
110
	public static function getAdapter()100%
111
	{
112
		return static::$adapter;
113
	}
114

                    
115
	protected function getFqdn($functionName)100%
116
	{
117
		return $this->defaultNamespace . $functionName;
118
	}
119

                    
120
	protected function generateIfNotExists($functionName)100%
121
	{
122
		if (isset($this->{$functionName}) === false)
123
		{
124
			$this->generate($functionName);
125
		}
126

                    
127
		return $this->getFqdn($functionName);
128
	}
129

                    
130
	protected function setDefaultBehavior($fqdn, \reflectionFunction $reflectedFunction = null)100%
131
	{
132
		$function = substr($fqdn, strrpos($fqdn, '\\') + 1);
133

                    
134
		if ($reflectedFunction === null)
135
		{
136
			$reflectedFunction = $this->buildReflectedFunction($function);
137
		}
138

                    
139
		if ($reflectedFunction === null)
140
		{
141
			$closure = function() { return null; };
142
		}
143
		else
144
		{
145
			$closure = eval('return function(' . static::getParametersSignature($reflectedFunction) . ') { return call_user_func_array(\'\\' . $function . '\', ' . static::getParameters($reflectedFunction) . '); };');
146
		}
147

                    
148
		static::$adapter->{$fqdn}->setClosure($closure);
149

                    
150
		return $this;
151
	}
152

                    
153
	protected function functionExists($fqdn)100%
154
	{
155
		return (isset(static::$adapter->{$fqdn}) === true);
156
	}
157

                    
158
	protected static function getParametersSignature(\reflectionFunction $function)85%
159
	{
160
		$parameters = array();
161

                    
162
		foreach (self::filterParameters($function) as $parameter)
163
		{
164
			$parameterCode = self::getParameterType($parameter) . ($parameter->isPassedByReference() == false ? '' : '& ') . '$' . $parameter->getName();
165

                    
166
			switch (true)
167
			{
168
				case $parameter->isDefaultValueAvailable():
169
					$parameterCode .= ' = ' . var_export($parameter->getDefaultValue(), true);
170
					break;
171

                    
172
				case $parameter->isOptional():
173
					$parameterCode .= ' = null';
174
			}
175

                    
176
			$parameters[] = $parameterCode;
177
		}
178

                    
179
		return join(', ', $parameters);
180
	}
181

                    
182
	protected static function getParameters(\reflectionFunction $function)100%
183
	{
184
		$parameters = array();
185

                    
186
		foreach (self::filterParameters($function) as $parameter)
187
		{
188
			$parameters[] = ($parameter->isPassedByReference() === false ? '' : '& ') . '$' . $parameter->getName();
189
		}
190

                    
191
		return 'array(' . join(',', $parameters) . ')';
192
	}
193

                    
194
	protected static function getParameterType(\reflectionParameter $parameter)70%
195
	{
196
		switch (true)
197
		{
198
			case $parameter->isArray():
199
				return 'array ';
200

                    
201
			case method_exists($parameter, 'isCallable') && $parameter->isCallable():
202
				return 'callable ';
203

                    
204
			case ($class = $parameter->getClass()):
205
				return '\\' . $class->getName() . ' ';
206

                    
207
			default:
208
				return '';
209
		}
210
	}
211

                    
212
	protected static function defineMockedFunction($namespace, $class, $function, \reflectionFunction $reflectedFunction = null)100%
213
	{
214
		eval(sprintf(
215
			'namespace %s { function %s(%s) { return \\%s::getAdapter()->invoke(__FUNCTION__, %s); } }',
216
			$namespace,
217
			$function,
218
			$reflectedFunction ? static::getParametersSignature($reflectedFunction) : '',
219
			$class,
220
			$reflectedFunction ? static::getParameters($reflectedFunction) : 'func_get_args()'
221
		));
222
	}
223

                    
224
	private function buildReflectedFunction($function)100%
225
	{
226
		$reflectedFunction = null;
227

                    
228
		try
229
		{
230
			$reflectedFunction = call_user_func_array($this->reflectedFunctionFactory, array($function));
231
		}
232
		catch (\exception $exception) {}
233

                    
234
		return $reflectedFunction;
235
	}
236

                    
237
	private static function filterParameters(\reflectionFunction $function)100%
238
	{
239
		return array_filter($function->getParameters(), function($parameter) { return ($parameter->getName() != '...'); });
240
	}
241
}
242

                    
243
mocker::setAdapter();