saintsystems / odata-client-php

OData Client Library for PHP
MIT License
141 stars 103 forks source link

flattenDictionary causes a type error in PHP 8 by calling method_exists without checking type of first parameter #124

Open trent-crawford opened 1 year ago

trent-crawford commented 1 year ago

SaintSystems\OData\ODataRequest::flattenDictionary() checks if the method exits on $arrayValue. $arrayValue could be an array itself, which would cause a type error on method_exits in PHP 8.

Existing method

/**
     * Flattens the property dictionaries into
     * JSON-friendly arrays
     *
     * @param mixed $obj the object to flatten
     *
     * @return array flattened object
     */
    protected function flattenDictionary($obj) {
        foreach ($obj as $arrayKey => $arrayValue) {
            if (method_exists($arrayValue, 'getProperties')) {
                $data = $arrayValue->getProperties();
                $obj[$arrayKey] = $data;
            } else {
                $data = $arrayValue;
            }
            if (is_array($data)) {
                $newItem = $this->flattenDictionary($data);
                $obj[$arrayKey] = $newItem;
            }
        }
        return $obj;
    }

I will open a pull request for the following change, where we check if $arrayValue is either a string or an object:

/**
     * Flattens the property dictionaries into
     * JSON-friendly arrays
     *
     * @param mixed $obj the object to flatten
     *
     * @return array flattened object
     */
    protected function flattenDictionary($obj) {
        foreach ($obj as $arrayKey => $arrayValue) {
            if ((is_string($arrayValue) || is_object($arrayValue)) && method_exists($arrayValue, 'getProperties')) {
                $data = $arrayValue->getProperties();
                $obj[$arrayKey] = $data;
            } else {
                $data = $arrayValue;
            }
            if (is_array($data)) {
                $newItem = $this->flattenDictionary($data);
                $obj[$arrayKey] = $newItem;
            }
        }
        return $obj;
    }