From d3049090af3002f9a0c41b99f00b610f19a15ca4 Mon Sep 17 00:00:00 2001 From: Rich Lott / Artful Robot Date: Tue, 10 Mar 2020 12:19:56 +0000 Subject: [PATCH] Fix array value accessing non existent properties on an ArrayAccess object --- CRM/Utils/Array.php | 3 ++- Civi/Payment/PropertyBag.php | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CRM/Utils/Array.php b/CRM/Utils/Array.php index 5c6b1ac923..1a3d8a0020 100644 --- a/CRM/Utils/Array.php +++ b/CRM/Utils/Array.php @@ -39,7 +39,8 @@ class CRM_Utils_Array { return array_key_exists($key, $list) ? $list[$key] : $default; } if ($list instanceof ArrayAccess) { - return $list[$key] ?? $default; + // ArrayAccess requires offsetExists is implemented for the equivalent to array_key_exists. + return $list->offsetExists($key) ? $list[$key] : $default; } // @todo - eliminate these from core & uncomment this line. // CRM_Core_Error::deprecatedFunctionWarning('You have passed an invalid parameter for the "list"'); diff --git a/Civi/Payment/PropertyBag.php b/Civi/Payment/PropertyBag.php index 6cea55241e..377e70ef7b 100644 --- a/Civi/Payment/PropertyBag.php +++ b/Civi/Payment/PropertyBag.php @@ -106,8 +106,8 @@ class PropertyBag implements \ArrayAccess { * @return bool TRUE if we have that value (on our default store) */ public function offsetExists ($offset): bool { - $prop = $this->handleLegacyPropNames($offset); - return isset($this->props['default'][$prop]); + $prop = $this->handleLegacyPropNames($offset, TRUE); + return $prop && isset($this->props['default'][$prop]); } /** @@ -199,16 +199,21 @@ class PropertyBag implements \ArrayAccess { /** * @param string $prop + * @param bool $silent if TRUE return NULL instead of throwing an exception. This is because offsetExists should be safe and not throw exceptions. * @return string canonical name. * @throws \InvalidArgumentException if prop name not known. */ - protected function handleLegacyPropNames($prop) { + protected function handleLegacyPropNames($prop, $silent = FALSE) { $newName = static::$propMap[$prop] ?? NULL; if ($newName === TRUE) { // Good, modern name. return $prop; } if ($newName === NULL) { + if ($silent) { + // Only for use by offsetExists + return; + } throw new \InvalidArgumentException("Unknown property '$prop'."); } // Remaining case is legacy name that's been translated. -- 2.25.1