Completed
Push — master ( 3be072...ba2d3a )
by Marco
231:32 queued 209:55
created

MagicIssetTest   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 3
lcom 1
cbo 1
dl 0
loc 146
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\ProxyGenerator\LazyLoadingGhost\MethodGenerator;
6
7
use PHPUnit\Framework\MockObject\MockObject;
8
use PHPUnit\Framework\TestCase;
9
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset;
10
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap;
11
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap;
12
use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap;
13
use ProxyManagerTestAsset\ClassWithMagicMethods;
14
use ProxyManagerTestAsset\ProxyGenerator\LazyLoading\MethodGenerator\ClassWithTwoPublicProperties;
15
use ReflectionClass;
16
use Zend\Code\Generator\MethodGenerator;
17
use Zend\Code\Generator\PropertyGenerator;
18
19
/**
20
 * Tests for {@see \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset}
21
 *
22
 * @group Coverage
23
 */
24
final class MagicIssetTest extends TestCase
25
{
26
    /** @var PropertyGenerator&MockObject */
27
    private PropertyGenerator $initializer;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
28
29
    /** @var MethodGenerator&MockObject */
30
    private MethodGenerator $initMethod;
31
32
    /** @var PublicPropertiesMap&MockObject */
33
    private PublicPropertiesMap $publicProperties;
34
35
    /** @var ProtectedPropertiesMap&MockObject */
36
    private ProtectedPropertiesMap $protectedProperties;
37
38
    /** @var PrivatePropertiesMap&MockObject */
39
    private PrivatePropertiesMap $privateProperties;
40
41
    private string $expectedCode = <<<'PHP'
42
$this->foo && $this->baz('__isset', array('name' => $name));
43
44
if (isset(self::$bar[$name])) {
45
    return isset($this->$name);
46
}
47
48
if (isset(self::$baz[$name])) {
49
    // check protected property access via compatible class
50
    $callers      = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
51
    $caller       = isset($callers[1]) ? $callers[1] : [];
52
    $object       = isset($caller['object']) ? $caller['object'] : '';
53
    $expectedType = self::$baz[$name];
54
55
    if ($object instanceof $expectedType) {
56
        return isset($this->$name);
57
    }
58
59
    $class = isset($caller['class']) ? $caller['class'] : '';
60
61
    if ($class === $expectedType || is_subclass_of($class, $expectedType)) {
62
        return isset($this->$name);
63
    }
64
} else {
65
    // check private property access via same class
66
    $callers = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
67
    $caller  = isset($callers[1]) ? $callers[1] : [];
68
    $class   = isset($caller['class']) ? $caller['class'] : '';
69
70
    static $accessorCache = [];
71
72
    if (isset(self::$tab[$name][$class])) {
73
        $cacheKey = $class . '#' . $name;
74
        $accessor = isset($accessorCache[$cacheKey])
75
            ? $accessorCache[$cacheKey]
76
            : $accessorCache[$cacheKey] = \Closure::bind(function ($instance) use ($name) {
77
                return isset($instance->$name);
78
            }, null, $class);
79
80
        return $accessor($this);
81
    }
82
83
    if ('ReflectionProperty' === $class) {
84
        $tmpClass = key(self::$tab[$name]);
85
        $cacheKey = $tmpClass . '#' . $name;
86
        $accessor = isset($accessorCache[$cacheKey])
87
            ? $accessorCache[$cacheKey]
88
            : $accessorCache[$cacheKey] = \Closure::bind(function ($instance) use ($name) {
89
                return isset($instance->$name);
90
            }, null, $tmpClass);
91
92
        return $accessor($this);
93
    }
94
}
95
%A
96
PHP;
97
98
    /**
99
     * {@inheritDoc}
100
     */
101
    protected function setUp() : void
102
    {
103
        $this->initializer         = $this->createMock(PropertyGenerator::class);
104
        $this->initMethod          = $this->createMock(MethodGenerator::class);
105
        $this->publicProperties    = $this
106
            ->getMockBuilder(PublicPropertiesMap::class)
107
            ->disableOriginalConstructor()
108
            ->getMock();
109
        $this->protectedProperties = $this
110
            ->getMockBuilder(ProtectedPropertiesMap::class)
111
            ->disableOriginalConstructor()
112
            ->getMock();
113
        $this->privateProperties   = $this
114
            ->getMockBuilder(PrivatePropertiesMap::class)
115
            ->disableOriginalConstructor()
116
            ->getMock();
117
118
        $this->initializer->method('getName')->willReturn('foo');
119
        $this->initMethod->method('getName')->willReturn('baz');
120
        $this->publicProperties->method('isEmpty')->willReturn(false);
121
        $this->publicProperties->method('getName')->willReturn('bar');
122
        $this->protectedProperties->method('getName')->willReturn('baz');
123
        $this->privateProperties->method('getName')->willReturn('tab');
124
    }
125
126
    /**
127
     * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset
128
     */
129
    public function testBodyStructureWithPublicProperties() : void
130
    {
131
        $magicIsset = new MagicIsset(
132
            new ReflectionClass(ClassWithTwoPublicProperties::class),
133
            $this->initializer,
134
            $this->initMethod,
135
            $this->publicProperties,
136
            $this->protectedProperties,
137
            $this->privateProperties
138
        );
139
140
        self::assertSame('__isset', $magicIsset->getName());
141
        self::assertCount(1, $magicIsset->getParameters());
142
143
        self::assertStringMatchesFormat($this->expectedCode, $magicIsset->getBody());
144
    }
145
146
    /**
147
     * @covers \ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset
148
     */
149
    public function testBodyStructureWithOverriddenMagicGet() : void
150
    {
151
        $magicIsset = new MagicIsset(
152
            new ReflectionClass(ClassWithMagicMethods::class),
153
            $this->initializer,
154
            $this->initMethod,
155
            $this->publicProperties,
156
            $this->protectedProperties,
157
            $this->privateProperties
158
        );
159
160
        self::assertSame('__isset', $magicIsset->getName());
161
        self::assertCount(1, $magicIsset->getParameters());
162
163
        $body = $magicIsset->getBody();
164
165
        self::assertStringMatchesFormat($this->expectedCode, $body);
166
        self::assertStringMatchesFormat('%Areturn parent::__isset($name);', $body);
167
    }
168
}
169