1 common.inc backdrop_sort(array &$array, array $keys = array('weight'), $dir = SORT_ASC)

Sort an array based on user-provided keys within that array.

// Sort by a single numeric key:
backdrop_sort($my_array, array('weight' => SORT_NUMERIC));

// Shorthand sort by a numeric key:
backdrop_sort($my_array, array('weight'));

// Sort by numeric and string keys.
backdrop_sort($my_array, array('weight' => SORT_NUMERIC, 'title' => SORT_STRING));

@since 1.9.0 The $dir parameter was added.

Parameters

array $array: The input array to be sorted.

array $keys: An array of keys to sort by. Values must be PHP sorting type flags, either SORT_NUMERIC or SORT_STRING, and default to SORT_NUMERIC if an unindexed array is passed in.

string $dir: The sort direction. Values must be either SORT_ASC or SORT_DESC.

Example usage:

File

core/includes/common.inc, line 7056
Common functions that many Backdrop modules will need to reference.

Code

function backdrop_sort(array &$array, array $keys = array('weight'), $dir = SORT_ASC) {
  // Ensure all keys have a sort value.
  $new_keys = array();
  foreach ($keys as $index => $sort) {
    if (is_string($sort) && is_int($index)) {
      $new_keys[$sort] = SORT_NUMERIC;
    }
    else {
      if ($sort === SORT_NUMERIC || $sort === SORT_STRING) {
        $new_keys[$index] = $sort;
      }
      else {
        // Fallback behavior for unexpected values. Untranslated to allow this
        // function to be used anywhere within Backdrop.
        $new_keys[$index] = SORT_NUMERIC;
        trigger_error('backdrop_sort() expects the second parameter to be an array keyed by strings and each value of the array to be either SORT_NUMERIC or SORT_STRING.', E_USER_WARNING);
      }
    }
  }
  $keys = $new_keys;

  // If sorting on a single value, optimize the sorting to sort only on that
  // specific key without the overhead of recursive handling.
  if (count($keys) === 1) {
    $key = key($keys);
    $key_sort = reset($keys);

    if ($key_sort === SORT_STRING) {
      uasort($array, function($a, $b) use ($key, $dir) {
        if (!is_array($a) || !is_array($b)) {
          return 0;
        }
        if (!isset($a[$key])) {
          $a[$key] = '';
        }
        if (!isset($b[$key])) {
          $b[$key] = '';
        }
        $cmp = strnatcasecmp($a[$key], $b[$key]);
        return ($dir == SORT_DESC) ? -$cmp : $cmp;
      });
    }
    else {
      uasort($array, function($a, $b) use ($key, $dir) {
        if (!is_array($a) || !is_array($b)) {
          return 0;
        }
        if (!isset($a[$key])) {
          $a[$key] = 0;
        }
        if (!isset($b[$key])) {
          $b[$key] = 0;
        }
        if ($a[$key] != $b[$key]) {
          $cmp = $a[$key] < $b[$key] ? -1 : 1;
          return ($dir == SORT_DESC) ? -$cmp : $cmp;
        }
        // Equal values, return 0.
        return 0;
      });
    }
  }
  // If doing a multiple-key comparison, use a recursive callback.
  else {
    $keys_map = array_keys($keys);
    $recursive_callback = function($a, $b, $key_index = 0) use ($keys, $keys_map, $dir, &$recursive_callback) {
      $key = $keys_map[$key_index];
      if (!is_array($a) || !is_array($b)) {
        return 0;
      }
      if (!isset($a[$key])) {
        $a[$key] = 0;
      }
      if (!isset($b[$key])) {
        $b[$key] = 0;
      }
      if ($a[$key] == $b[$key]) {
        // Sort on the next key if one exists.
        if (isset($keys_map[$key_index + 1])) {
          return $recursive_callback($a, $b, $key_index + 1);
        }
      }
      else {
        $cmp = 0;
        if ($keys[$key] === SORT_STRING) {
          $cmp = strnatcasecmp($a[$key], $b[$key]);
        }
        else {
          $cmp = ($a[$key] < $b[$key]) ? -1 : 1;
        }
        return ($dir == SORT_DESC) ? -$cmp : $cmp;
      }
      return 0;
    };
    uasort($array, $recursive_callback);
  }
}