Moka::getCurrentTestCase()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

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