<?php
$data = [
['word' => 'foo'],
['word' => 'BAR'],
['word' => 'FOO'],
['word' => 'bar'],
];
usort($data, make_comparer
(['word', SORT_ASC
, 'strtolower']));
function make_comparer() {
// Normalize criteria up front so that the comparer finds everything tidy
foreach ($criteria as $index => $criterion) {
$criteria[$index] = is_array($criterion) : array($criterion, SORT_ASC
, null); }
return function($first, $second) use (&$criteria) {
foreach ($criteria as $criterion) {
// How will we compare this round?
list($column, $sortOrder, $projection) = $criterion; $sortOrder = $sortOrder === SORT_DESC ? -1 : 1;
// If a projection was defined project the values now
if ($projection) {
}
else {
$lhs = $first[$column];
$rhs = $second[$column];
}
// Do the actual comparison; do not return if equal
if ($lhs < $rhs) {
return -1 * $sortOrder;
}
else if ($lhs > $rhs) {
return 1 * $sortOrder;
}
}
return 0; // tiebreakers exhausted, so $first == $second
};
}
PD9waHAKCiRkYXRhID0gWwoJWyd3b3JkJyA9PiAnZm9vJ10sCglbJ3dvcmQnID0+ICdCQVInXSwKCVsnd29yZCcgPT4gJ0ZPTyddLAoJWyd3b3JkJyA9PiAnYmFyJ10sCl07Cgp1c29ydCgkZGF0YSwgbWFrZV9jb21wYXJlcihbJ3dvcmQnLCBTT1JUX0FTQywgJ3N0cnRvbG93ZXInXSkpOwpwcmludF9yKCRkYXRhKTsKCgpmdW5jdGlvbiBtYWtlX2NvbXBhcmVyKCkgewogICAgLy8gTm9ybWFsaXplIGNyaXRlcmlhIHVwIGZyb250IHNvIHRoYXQgdGhlIGNvbXBhcmVyIGZpbmRzIGV2ZXJ5dGhpbmcgdGlkeQogICAgJGNyaXRlcmlhID0gZnVuY19nZXRfYXJncygpOwogICAgZm9yZWFjaCAoJGNyaXRlcmlhIGFzICRpbmRleCA9PiAkY3JpdGVyaW9uKSB7CiAgICAgICAgJGNyaXRlcmlhWyRpbmRleF0gPSBpc19hcnJheSgkY3JpdGVyaW9uKQogICAgICAgICAgICA/IGFycmF5X3BhZCgkY3JpdGVyaW9uLCAzLCBudWxsKQogICAgICAgICAgICA6IGFycmF5KCRjcml0ZXJpb24sIFNPUlRfQVNDLCBudWxsKTsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24oJGZpcnN0LCAkc2Vjb25kKSB1c2UgKCYkY3JpdGVyaWEpIHsKICAgICAgICBmb3JlYWNoICgkY3JpdGVyaWEgYXMgJGNyaXRlcmlvbikgewogICAgICAgICAgICAvLyBIb3cgd2lsbCB3ZSBjb21wYXJlIHRoaXMgcm91bmQ/CiAgICAgICAgICAgIGxpc3QoJGNvbHVtbiwgJHNvcnRPcmRlciwgJHByb2plY3Rpb24pID0gJGNyaXRlcmlvbjsKICAgICAgICAgICAgJHNvcnRPcmRlciA9ICRzb3J0T3JkZXIgPT09IFNPUlRfREVTQyA/IC0xIDogMTsKCiAgICAgICAgICAgIC8vIElmIGEgcHJvamVjdGlvbiB3YXMgZGVmaW5lZCBwcm9qZWN0IHRoZSB2YWx1ZXMgbm93CiAgICAgICAgICAgIGlmICgkcHJvamVjdGlvbikgewogICAgICAgICAgICAgICAgJGxocyA9IGNhbGxfdXNlcl9mdW5jKCRwcm9qZWN0aW9uLCAkZmlyc3RbJGNvbHVtbl0pOwogICAgICAgICAgICAgICAgJHJocyA9IGNhbGxfdXNlcl9mdW5jKCRwcm9qZWN0aW9uLCAkc2Vjb25kWyRjb2x1bW5dKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICRsaHMgPSAkZmlyc3RbJGNvbHVtbl07CiAgICAgICAgICAgICAgICAkcmhzID0gJHNlY29uZFskY29sdW1uXTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gRG8gdGhlIGFjdHVhbCBjb21wYXJpc29uOyBkbyBub3QgcmV0dXJuIGlmIGVxdWFsCiAgICAgICAgICAgIGlmICgkbGhzIDwgJHJocykgewogICAgICAgICAgICAgICAgcmV0dXJuIC0xICogJHNvcnRPcmRlcjsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmICgkbGhzID4gJHJocykgewogICAgICAgICAgICAgICAgcmV0dXJuIDEgKiAkc29ydE9yZGVyOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gMDsgLy8gdGllYnJlYWtlcnMgZXhoYXVzdGVkLCBzbyAkZmlyc3QgPT0gJHNlY29uZAogICAgfTsKfQ==