Skip to content

Proposed improvements in Horde_Array and Horde\Util\ArrayUtils #15

@amulet1

Description

@amulet1

There are several functions which should be improved:

  • Some of the functions are recursive, but can be easily changed to non-recursive implementation
  • Some of the functions have side effects when they unexpectedly (and unnecessary) modify parameters passed by reference
  • Optimizations are possible if we lightly modify the behavior (e.g. parameters handling or return values)

Let's look at getElement() as an example:

public static function getElement(&$array, array &$keys, $value = null)
{
    if (count($keys)) {
        $key = array_shift($keys);
        return isset($array[$key])
            ? self::getElement($array[$key], $keys, $value)
            : false;
    }

     if (!is_null($value)) {
        $array = $value;
    }

    return $array;
}
  1. The function modifies $array contents, but only if $value is not null.
    Proposal: Drop $value parameter from getElement(). Use setElement() for the only case in Horde_Form_type_image::getUploadedFileType() where the $array is modified.

  2. The function modifies $keys array (removes all elements). This is an unneeded side effect, and it looks like existing code does not rely on it anywhere.
    Proposal: Remove & from &$keys.

  3. The function is recursive.
    Proposal: Make it non-recursive.

  4. In some existing case(s) it would be beneficial to support a case when $keys is a string with a single key.
    For example, in Horde::getDriverConfig($backend, $type = 'sql')):

    if (is_array($backend)) {
        $c = Horde_Array::getElement($conf, $backend);
    } elseif (isset($conf[$backend])) {
        $c = $conf[$backend];
    } else {
        $c = null;
    }

Proposal: Support string in $keys parameter. Additionally, if we modify getElement() to return null instead of false for non-existent properties, then the above snippet could be simplified to just this:

    $c = Horde_Array::getElement($conf, $backend);

And it looks like this will not cause issues with the existing code. Here is one place in Horde_Core_Perms::getAvailable() where the return value is checked for false:

   $children = Horde_Array::getElement($perms['tree'], $levels);
    if (($children === false) ||
        !is_array($children) ||
        !count($children)) {
        /* No array of children available for this permission name. */
        return false;
    }

If returned value becomes null instead of false, it still would still trigger !is_array() check (but we could also adjust the code).


With the above proposals the getElement() function transforms into this:

public static function getElement($array, $keys)
{
    $ref = &$array;

    foreach ((array) $keys as $key) {
        if (!isset($ref[$key])) {
            return null;
        }
        $ref = &$ref[$key];
    }

    return $ref;
}

Other functions should be modified in similar way.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions