Completed
Pull Request — master (#44)
by Angelo
01:54
created

Moka::ensurePluginLoad()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Moka;
5
6
use Mockery\MockInterface;
7
use Moka\Exception\InvalidIdentifierException;
8
use Moka\Exception\MissingDependencyException;
9
use Moka\Exception\MockNotCreatedException;
10
use Moka\Exception\NotImplementedException;
11
use Moka\Factory\ProxyBuilderFactory;
12
use function Moka\Plugin\loadPlugin;
13
use Moka\Proxy\ProxyInterface;
14
use Moka\Proxy\ProxyTrait;
15
use Moka\Strategy\MockingStrategyInterface;
16
use Phake_IMock as PhakeMock;
17
use PHPUnit\Framework\MockObject\MockObject;
18
use PHPUnit\Framework\TestCase;
19
use Prophecy\Prophecy\ObjectProphecy;
20
use Prophecy\Prophet;
21
22
/**
23
 * Class Moka
24
 * @package Moka
25
 *
26
 * @method static MockInterface|ProxyInterface mockery(string $fqcnOrAlias, string $alias = null)
27
 * @method static PhakeMock|ProxyInterface phake(string $fqcnOrAlias, string $alias = null)
28
 */
29
class Moka
30
{
31
    /**
32
     * @var array|MockingStrategyInterface[]
33
     */
34
    private static $mockingStrategies = [];
35
36
    /**
37
     * @param string $name
38
     * @param array $arguments
39
     * @return ProxyInterface
40
     *
41
     * @throws NotImplementedException
42
     * @throws InvalidIdentifierException
43
     * @throws MockNotCreatedException
44
     * @throws MissingDependencyException
45
     */
46 2
    public static function __callStatic(string $name, array $arguments): ProxyInterface
47
    {
48 2
        return self::getProxy($name, $arguments);
49
    }
50
51
    /**
52
     * @param string $fqcnOrAlias
53
     * @param string|null $alias
54
     * @return MockObject|ProxyInterface
55
     *
56
     * @throws NotImplementedException
57
     * @throws InvalidIdentifierException
58
     * @throws MockNotCreatedException
59
     * @throws MissingDependencyException
60
     */
61 3
    public static function phpunit(string $fqcnOrAlias, string $alias = null): ProxyInterface
62
    {
63
        /** @var ProxyInterface|ProxyTrait $proxy */
64 3
        $proxy = self::getProxy('phpunit', [$fqcnOrAlias, $alias]);
65
66 3
        if (null !== $testCase = self::getCurrentTestCase()) {
67 3
            $testCase->registerMockObject($proxy->__moka_getMock());
68
        }
69
70 3
        return $proxy;
71
    }
72
73
    /**
74
     * @param string $fqcnOrAlias
75
     * @param string|null $alias
76
     * @return ObjectProphecy|ProxyInterface
77
     *
78
     * @throws \ReflectionException
79
     * @throws NotImplementedException
80
     * @throws InvalidIdentifierException
81
     * @throws MockNotCreatedException
82
     * @throws MissingDependencyException
83
     */
84 2
    public static function prophecy(string $fqcnOrAlias, string $alias = null): ProxyInterface
85
    {
86
        /** @var ProxyInterface|ProxyTrait $proxy */
87 2
        $proxy = self::getProxy('prophecy', [$fqcnOrAlias, $alias]);
88
89 2
        if (null !== $testCase = self::getCurrentTestCase()) {
90 2
            $prophetProperty = new \ReflectionProperty(
91 2
                TestCase::class,
92 2
                'prophet'
93
            );
94
95 2
            $prophetProperty->setAccessible(true);
96 2
            if (null === $prophet = $prophetProperty->getValue($testCase)) {
97 2
                $prophet = new Prophet();
98 2
                $prophetProperty->setValue($testCase, $prophet);
99
            }
100
101 2
            $propheciesProperty = new \ReflectionProperty(
102 2
                Prophet::class,
103 2
                'prophecies'
104
            );
105 2
            $propheciesProperty->setAccessible(true);
106
107
            /** @var ObjectProphecy[] $prophecies */
108 2
            $prophecies = $propheciesProperty->getValue($prophet) ?: [];
109 2
            $prophecies[] = $proxy->__moka_getMock();
110
111 2
            $propheciesProperty->setValue($prophet, $prophecies);
112
        }
113
114 2
        return $proxy;
115
    }
116
117
    /**
118
     * @return void
119
     */
120 1
    public static function clean()
121
    {
122 1
        ProxyBuilderFactory::reset();
123
    }
124
125
    /**
126
     * @return TestCase|null
127
     */
128 4
    private static function getCurrentTestCase()
129
    {
130 4
        $backtrace = debug_backtrace();
131 4
        foreach ($backtrace as $frame) {
132 4
            if (!isset($frame['object'])) {
133 4
                continue;
134
            }
135
136 4
            $object = $frame['object'];
137 4
            if ($object instanceof TestCase) {
138 4
                return $object;
139
            }
140
141
            // @codeCoverageIgnoreStart
142
            return null;
143
            // @codeCoverageIgnoreEnd
144
        }
145
146
        // @codeCoverageIgnoreStart
147
        return null;
148
        // @codeCoverageIgnoreEnd
149
    }
150
151
    /**
152
     * @param string $name
153
     * @param array $arguments
154
     * @return ProxyInterface
155
     *
156
     * @throws NotImplementedException
157
     * @throws InvalidIdentifierException
158
     * @throws MockNotCreatedException
159
     * @throws MissingDependencyException
160
     */
161 5
    private static function getProxy(string $name, array $arguments): ProxyInterface
162
    {
163 5
        self::ensurePluginLoad($name);
164
165 4
        $fqcnOrAlias = $arguments[0];
166 4
        $alias = $arguments[1] ?? null;
167
168 4
        return ProxyBuilderFactory::get(self::$mockingStrategies[$name])
169 4
            ->getProxy($fqcnOrAlias, $alias);
170
    }
171
172
    /**
173
     * @param string $pluginName
174
     * @throws MissingDependencyException
175
     * @throws NotImplementedException
176
     */
177 5
    private static function ensurePluginLoad(string $pluginName): void
178
    {
179 5
        if (!array_key_exists($pluginName, self::$mockingStrategies)) {
180 2
            self::$mockingStrategies[$pluginName] = loadPlugin($pluginName);
181
        }
182
    }
183
}
184