Repository: Roave/BetterReflection (php)

Issue:
ReflectionObject adapter does not override getReflectionConstants
See the failing test case at 0f50ad73cbf2dff7e7252864680e16ce20603e1e and the [thrown exception in core](https://github.com/php/php-src/blob/php-7.4.13/ext/reflection/php_reflection.c#L98):
```php

            ['getConstant', null, 'a', ['foo']],
            ['getConstants', null, ['a', 'b'], []],
+           ['getReflectionConstants', null, ['a', 'b'], []],
            ['getInterfaces', null, [$mockClassLike], []],
```
```
1) Roave\BetterReflectionTest\Reflection\Adapter\ReflectionObjectTest::testAdapterMethods with data set #20 ('getReflectionConstants', null, array('a', 'b'), array())
Error: Internal error: Failed to retrieve the reflection object

/home/nomad/Code/BetterReflection/test/unit/Reflection/Adapter/ReflectionObjectTest.php:128
```

Pull request:
Add missing methods to ReflectionObject adapter
Fixes #715.

Patch:
diff --git a/src/Reflection/Adapter/ReflectionObject.php b/src/Reflection/Adapter/ReflectionObject.php
index 25529d0f..91c8018f 100644
--- a/src/Reflection/Adapter/ReflectionObject.php
+++ b/src/Reflection/Adapter/ReflectionObject.php
@@ -257,6 +257,33 @@ class ReflectionObject extends CoreReflectionObject
         return $this->betterReflectionObject->getConstant($name);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getReflectionConstant($name)
+    {
+        $betterReflectionConstant = $this->betterReflectionObject->getReflectionConstant($name);
+
+        if ($betterReflectionConstant === null) {
+            return false;
+        }
+
+        return new ReflectionClassConstant($betterReflectionConstant);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getReflectionConstants()
+    {
+        return array_values(array_map(
+            static function (BetterReflectionClassConstant $betterConstant): ReflectionClassConstant {
+                return new ReflectionClassConstant($betterConstant);
+            },
+            $this->betterReflectionObject->getReflectionConstants(),
+        ));
+    }
+
     /**
      * {@inheritDoc}
      */


Test patch:
diff --git a/test/unit/Reflection/Adapter/ReflectionObjectTest.php b/test/unit/Reflection/Adapter/ReflectionObjectTest.php
index 20f3a823..a543fd0f 100644
--- a/test/unit/Reflection/Adapter/ReflectionObjectTest.php
+++ b/test/unit/Reflection/Adapter/ReflectionObjectTest.php
@@ -10,6 +10,7 @@ use ReflectionException as CoreReflectionException;
 use ReflectionObject as CoreReflectionObject;
 use ReflectionProperty as CoreReflectionProperty;
 use Roave\BetterReflection\Reflection\Adapter\Exception\NotImplemented;
+use Roave\BetterReflection\Reflection\Adapter\ReflectionClassConstant as ReflectionClassConstantAdapter;
 use Roave\BetterReflection\Reflection\Adapter\ReflectionObject as ReflectionObjectAdapter;
 use Roave\BetterReflection\Reflection\ReflectionClass as BetterReflectionClass;
 use Roave\BetterReflection\Reflection\ReflectionClassConstant as BetterReflectionClassConstant;
@@ -55,6 +56,8 @@ class ReflectionObjectTest extends TestCase
 
         $mockClassLike = $this->createMock(BetterReflectionClass::class);
 
+        $mockConstant = $this->createMock(BetterReflectionClassConstant::class);
+
         return [
             ['__toString', null, '', []],
             ['getName', null, '', []],
@@ -75,6 +78,8 @@ class ReflectionObjectTest extends TestCase
             ['getProperties', null, [$mockProperty], []],
             ['hasConstant', null, true, ['foo']],
             ['getConstant', null, 'a', ['foo']],
+            ['getReflectionConstant', null, $mockConstant, ['foo']],
+            ['getReflectionConstants', null, [$mockConstant], []],
             ['getInterfaces', null, [$mockClassLike], []],
             ['getInterfaceNames', null, ['a', 'b'], []],
             ['isInterface', null, true, []],
@@ -497,4 +502,50 @@ class ReflectionObjectTest extends TestCase
         self::assertCount(1, $protectedConstants);
         self::assertEquals([$protectedBetterReflectionClassConstant->getName() => $protectedBetterReflectionClassConstant->getValue()], $protectedConstants);
     }
+
+    public function testGetReflectionConstantReturnsFalseWhenConstantDoesNotExist(): void
+    {
+        $betterReflectionObject = $this->createMock(BetterReflectionObject::class);
+
+        $betterReflectionObject
+            ->expects($this->once())
+            ->method('getReflectionConstant')
+            ->with('NON_EXISTENT_CONSTANT')
+            ->willReturn(null);
+
+        $reflectionObjectAdapter = new ReflectionObjectAdapter($betterReflectionObject);
+
+        self::assertFalse($reflectionObjectAdapter->getReflectionConstant('NON_EXISTENT_CONSTANT'));
+    }
+
+    public function testGetReflectionConstantReturnsClassConstantAdapterWhenConstantExists(): void
+    {
+        $betterReflectionObject        = $this->createMock(BetterReflectionObject::class);
+        $betterReflectionClassConstant = $this->createMock(BetterReflectionClassConstant::class);
+
+        $betterReflectionObject
+            ->expects($this->once())
+            ->method('getReflectionConstant')
+            ->with('SOME_CONSTANT')
+            ->willReturn($betterReflectionClassConstant);
+
+        $reflectionObjectAdapter = new ReflectionObjectAdapter($betterReflectionObject);
+
+        self::assertInstanceOf(ReflectionClassConstantAdapter::class, $reflectionObjectAdapter->getReflectionConstant('SOME_CONSTANT'));
+    }
+
+    public function testGetReflectionConstantsReturnsClassConstantAdapter(): void
+    {
+        $betterReflectionObject        = $this->createMock(BetterReflectionObject::class);
+        $betterReflectionClassConstant = $this->createMock(BetterReflectionClassConstant::class);
+
+        $betterReflectionObject
+            ->expects($this->once())
+            ->method('getReflectionConstants')
+            ->willReturn([$betterReflectionClassConstant]);
+
+        $reflectionObjectAdapter = new ReflectionObjectAdapter($betterReflectionObject);
+
+        self::assertContainsOnlyInstancesOf(ReflectionClassConstantAdapter::class, $reflectionObjectAdapter->getReflectionConstants());
+    }
 }