Sorter::sort()   B
last analyzed

Complexity

Conditions 9
Paths 5

Size

Total Lines 41
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 20
c 2
b 0
f 0
nc 5
nop 2
dl 0
loc 41
rs 8.0555
1
<?php
2
namespace Darya\Storage;
3
4
/**
5
 * Sorts record sets using an array-based syntax.
6
 *
7
 * For sorting in-memory storage.
8
 *
9
 * @author Chris Andrew <[email protected]>
10
 */
11
class Sorter
12
{
13
	/**
14
	 * Normalize the given sorting order array.
15
	 *
16
	 * @param array $order
17
	 * @return array
18
	 */
19
	protected static function normalizeOrder(array $order = array())
20
	{
21
		$result = array();
22
23
		foreach ($order as $key => $value) {
24
			if (!is_string($key)) {
25
				$result[$value] = 'asc';
26
27
				continue;
28
			}
29
30
			$result[$key] = strtolower($value);
31
		}
32
33
		return $result;
34
	}
35
36
	/**
37
	 * Prepare the given sorting order.
38
	 *
39
	 * @param array|string $order
40
	 * @return array
41
	 */
42
	protected static function prepareOrder($order)
43
	{
44
		if (is_array($order)) {
45
			return static::normalizeOrder($order);
46
		}
47
48
		if (!is_string($order)) {
0 ignored issues
show
introduced by
The condition is_string($order) is always true.
Loading history...
49
			return array();
50
		}
51
52
		return array($order => 'asc');
53
	}
54
55
	/**
56
	 * Sort data using the given order.
57
	 *
58
	 * Uses indexes to retain order of equal elements - stable sorting.
59
	 *
60
	 * @param array        $data
61
	 * @param array|string $order [optional]
62
	 * @return array
63
	 */
64
	public function sort(array $data, $order = array())
65
	{
66
		$order = $this->prepareOrder($order);
67
68
		if (empty($order)) {
69
			return $data;
70
		}
71
72
		$index = 0;
73
74
		foreach ($data as &$item) {
75
			$item = array($index++, $item);
76
		}
77
78
		usort($data, function ($a, $b) use ($order) {
79
			foreach ($order as $field => $direction) {
80
				if (!isset($a[1][$field]) || !isset($b[1][$field])) {
81
					continue;
82
				}
83
84
				$result = strnatcasecmp($a[1][$field], $b[1][$field]);
85
86
				if ($result === 0) {
87
					continue;
88
				}
89
90
				if ($direction === 'desc') {
91
					return $result - $result * 2;
92
				}
93
94
				return $result;
95
			}
96
97
			return $a[0] - $b[0];
98
		});
99
100
		foreach ($data as &$item) {
101
			$item = $item[1];
102
		}
103
104
		return $data;
105
	}
106
}
107