Skip to content

Commit

Permalink
Fix bug: can't stub static method in parent class (#155)
Browse files Browse the repository at this point in the history
  • Loading branch information
freeaquar authored and DavertMik committed Jul 31, 2018
1 parent 454a710 commit 0613866
Showing 1 changed file with 83 additions and 40 deletions.
123 changes: 83 additions & 40 deletions src/AspectMock/Core/Mocker.php
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
<?php

namespace AspectMock\Core;

use AspectMock\Intercept\FunctionInjector;
use Go\Aop\Aspect;
use AspectMock\Intercept\MethodInvocation;

class Mocker implements Aspect {
class Mocker implements Aspect
{

protected $classMap = [];
protected $objectMap = [];
protected $funcMap = [];
protected $methodMap = ['__call', '__callStatic'];
protected $classMap = [];
protected $objectMap = [];
protected $funcMap = [];
protected $methodMap = ['__call', '__callStatic'];
protected $dynamicMethods = ['__call', '__callStatic'];

public function fakeMethodsAndRegisterCalls($class, $declaredClass, $method, $params, $static)
{
// $method = $invocation->getMethod();
// $obj = $invocation->getThis();
$result = __AM_CONTINUE__;

if (in_array($method, $this->methodMap)) {
Expand All @@ -35,19 +36,25 @@ public function fakeMethodsAndRegisterCalls($class, $declaredClass, $method, $pa
}

if (!$static) {
if (isset($this->objectMap[spl_object_hash($class)])) Registry::registerInstanceCall($class, $method, $params);
if (isset($this->objectMap[spl_object_hash($class)])) {
Registry::registerInstanceCall($class, $method, $params);
}
$class = get_class($class);
}

if (isset($this->classMap[$class])) Registry::registerClassCall($class, $method, $params);
if ($class != $declaredClass && isset($this->classMap[$declaredClass])) Registry::registerClassCall($declaredClass, $method, $params);
if (isset($this->classMap[$class])) {
Registry::registerClassCall($class, $method, $params);
}
if ($class != $declaredClass && isset($this->classMap[$declaredClass])) {
Registry::registerClassCall($declaredClass, $method, $params);
}

return $result;
}

public function fakeFunctionAndRegisterCalls($namespace, $function, $args)
{
$result = __AM_CONTINUE__;
$result = __AM_CONTINUE__;
$fullFuncName = "$namespace\\$function";
Registry::registerFunctionCall($fullFuncName, $args);

Expand All @@ -65,57 +72,83 @@ public function fakeFunctionAndRegisterCalls($namespace, $function, $args)
protected function invokeFakedMethods(MethodInvocation $invocation)
{
$method = $invocation->getMethod();
if (!in_array($method, $this->methodMap)) return __AM_CONTINUE__;
if (!in_array($method, $this->methodMap)) {
return __AM_CONTINUE__;
}

$obj = $invocation->getThis();

if (is_object($obj)) {
// instance method
$params = $this->getObjectMethodStubParams($obj, $method);
if ($params !== false) return $this->stub($invocation, $params);
if ($params !== false) {
return $this->stub($invocation, $params);
}

// class method
$params = $this->getClassMethodStubParams(get_class($obj), $method);
if ($params !== false) return $this->stub($invocation, $params);
if ($params !== false) {
return $this->stub($invocation, $params);
}

// inheritance
$params = $this->getClassMethodStubParams($invocation->getDeclaredClass(), $method);
if ($params !== false) return $this->stub($invocation, $params);
if ($params !== false) {
return $this->stub($invocation, $params);
}

// magic methods
if ($method == '__call') {
$args = $invocation->getArguments();
$args = $invocation->getArguments();
$method = array_shift($args);

$params = $this->getObjectMethodStubParams($obj, $method);
if ($params !== false) return $this->stubMagicMethod($invocation, $params);
if ($params !== false) {
return $this->stubMagicMethod($invocation, $params);
}

// magic class method
$params = $this->getClassMethodStubParams(get_class($obj), $method);
if ($params !== false) return $this->stubMagicMethod($invocation, $params);
if ($params !== false) {
return $this->stubMagicMethod($invocation, $params);
}

// inheritance
$calledClass = $invocation->getDeclaredClass();
$params = $this->getClassMethodStubParams($calledClass, $method);
if ($params !== false) return $this->stubMagicMethod($invocation, $params);
$params = $this->getClassMethodStubParams($calledClass, $method);
if ($params !== false) {
return $this->stubMagicMethod($invocation, $params);
}
}
} else {
// static method
$params = $this->getClassMethodStubParams($obj, $method);
if ($params !== false) return $this->stub($invocation, $params);
if ($params !== false) {
return $this->stub($invocation, $params);
}

// inheritance
$params = $this->getClassMethodStubParams($invocation->getDeclaredClass(), $method);
if ($params !== false) {
return $this->stub($invocation, $params);
}

// magic static method (facade)
if ($method == '__callStatic') {
$args = $invocation->getArguments();
$args = $invocation->getArguments();
$method = array_shift($args);

$params = $this->getClassMethodStubParams($obj, $method);
if ($params !== false) return $this->stubMagicMethod($invocation, $params);
if ($params !== false) {
return $this->stubMagicMethod($invocation, $params);
}

// inheritance
$calledClass = $invocation->getDeclaredClass();
$params = $this->getClassMethodStubParams($calledClass, $method);
if ($params !== false) return $this->stubMagicMethod($invocation, $params);
$params = $this->getClassMethodStubParams($calledClass, $method);
if ($params !== false) {
return $this->stubMagicMethod($invocation, $params);
}
}
}
return __AM_CONTINUE__;
Expand All @@ -124,17 +157,25 @@ protected function invokeFakedMethods(MethodInvocation $invocation)
protected function getObjectMethodStubParams($obj, $method_name)
{
$oid = spl_object_hash($obj);
if (!isset($this->objectMap[$oid])) return false;
if (!isset($this->objectMap[$oid])) {
return false;
}
$params = $this->objectMap[$oid];
if (!array_key_exists($method_name,$params)) return false;
if (!array_key_exists($method_name, $params)) {
return false;
}
return $params;
}

protected function getClassMethodStubParams($class_name, $method_name)
{
if (!isset($this->classMap[$class_name])) return false;
if (!isset($this->classMap[$class_name])) {
return false;
}
$params = $this->classMap[$class_name];
if (!array_key_exists($method_name,$params)) return false;
if (!array_key_exists($method_name, $params)) {
return false;
}
return $params;
}

Expand Down Expand Up @@ -173,35 +214,37 @@ protected function stubMagicMethod(MethodInvocation $invocation, $params)

protected function turnToClosure($returnValue)
{
if ($returnValue instanceof \Closure) return $returnValue;
return function() use ($returnValue) {
if ($returnValue instanceof \Closure) {
return $returnValue;
}
return function () use ($returnValue) {
return $returnValue;
};
}

public function registerClass($class, $params = array())
public function registerClass($class, $params = [])
{
$class = ltrim($class,'\\');
$class = ltrim($class, '\\');
if (isset($this->classMap[$class])) {
$params = array_merge($this->classMap[$class], $params);
}
$this->methodMap = array_merge($this->methodMap, array_keys($params));
$this->methodMap = array_merge($this->methodMap, array_keys($params));
$this->classMap[$class] = $params;
}

public function registerObject($object, $params = array())
public function registerObject($object, $params = [])
{
$hash = spl_object_hash($object);
if (isset($this->objectMap[$hash])) {
$params = array_merge($this->objectMap[$hash], $params);
}
$this->objectMap[$hash] = $params;
$this->methodMap = array_merge($this->methodMap, array_keys($params));
$this->methodMap = array_merge($this->methodMap, array_keys($params));
}

public function registerFunc($namespace, $func, $body)
{
$namespace = ltrim($namespace,'\\');
$namespace = ltrim($namespace, '\\');
if (!function_exists("$namespace\\$func")) {
$injector = new FunctionInjector($namespace, $func);
$injector->save();
Expand All @@ -213,10 +256,10 @@ public function registerFunc($namespace, $func, $body)
public function clean($objectOrClass = null)
{
if (!$objectOrClass) {
$this->classMap = [];
$this->classMap = [];
$this->objectMap = [];
$this->methodMap = ['__call','__callStatic'];
$this->funcMap = [];
$this->methodMap = ['__call', '__callStatic'];
$this->funcMap = [];
} elseif (is_object($objectOrClass)) {
unset($this->objectMap[spl_object_hash($objectOrClass)]);
} else {
Expand Down

0 comments on commit 0613866

Please sign in to comment.