FIX Harden hasMethod() against invalid values

This method should typehint the incoming value once union types are
available, but for now this ensures that method_exists() is not called
on scalar values, which is unsupported in PHP 8.
This commit is contained in:
Garion Herman 2020-10-23 16:33:56 +13:00
parent 91f831cd0b
commit e89ae93ac9
3 changed files with 73 additions and 4 deletions

View File

@ -400,7 +400,7 @@ class ClassInfo
*/
public static function hasMethod($object, $method)
{
if (empty($object)) {
if (empty($object) || (!is_object($object) && !is_string($object))) {
return false;
}
if (method_exists($object, $method)) {

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Core\Tests;
use DateTime;
use ReflectionException;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Tests\ClassInfoTest\BaseClass;
@ -15,6 +16,7 @@ use SilverStripe\Core\Tests\ClassInfoTest\ExtensionTest1;
use SilverStripe\Core\Tests\ClassInfoTest\ExtensionTest2;
use SilverStripe\Core\Tests\ClassInfoTest\GrandChildClass;
use SilverStripe\Core\Tests\ClassInfoTest\HasFields;
use SilverStripe\Core\Tests\ClassInfoTest\HasMethod;
use SilverStripe\Core\Tests\ClassInfoTest\NoFields;
use SilverStripe\Core\Tests\ClassInfoTest\WithCustomTable;
use SilverStripe\Core\Tests\ClassInfoTest\WithRelation;
@ -266,9 +268,57 @@ class ClassInfoTest extends SapphireTest
);
}
/**
* @dataProvider provideClassSpecCases
*/
/** @dataProvider provideHasMethodCases */
public function testHasMethod($object, $method, $output)
{
$this->assertEquals(
$output,
ClassInfo::hasMethod($object, $method)
);
}
public function provideHasMethodCases()
{
return [
'Basic object' => [
new DateTime(),
'format',
true,
],
'CustomMethod object' => [
new HasMethod(),
'example',
true,
],
'Class Name' => [
'DateTime',
'format',
true,
],
'FQCN' => [
'\DateTime',
'format',
true,
],
'Invalid FQCN' => [
'--GreatTime',
'format',
false,
],
'Integer' => [
1,
'format',
false,
],
'Array' => [
['\DateTime'],
'format',
false,
],
];
}
/** @dataProvider provideClassSpecCases */
public function testParseClassSpec($input, $output)
{
$this->assertEquals(

View File

@ -0,0 +1,19 @@
<?php
namespace SilverStripe\Core\Tests\ClassInfoTest;
use SilverStripe\Core\CustomMethods;
use SilverStripe\Dev\TestOnly;
/**
* Example of class with hasMethod() implementation
*/
class HasMethod implements TestOnly
{
use CustomMethods;
public function example()
{
return true;
}
}