Sorter   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 37
c 1
b 0
f 0
dl 0
loc 92
ccs 36
cts 36
cp 1
rs 10
wmc 12

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 3
A getOrder() 0 15 3
A __invoke() 0 25 3
A getComparisonField() 0 9 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\SkeletonMapper\DataSource;
6
7
use InvalidArgumentException;
8
use function count;
9
use function is_string;
10
use function sprintf;
11
use function strtolower;
12
13
class Sorter
14
{
15
    private const ORDER_ASC  = 'asc';
16
    private const ORDER_DESC = 'desc';
17
18
    /** @var int */
19
    private $level = 0;
20
21
    /** @var string[] */
22
    private $fields;
23
24
    /** @var int[] */
25
    private $orders;
26
27
    /**
28
     * @param string[] $orderBy
29
     */
30 9
    public function __construct(array $orderBy)
31
    {
32 9
        if ($orderBy === []) {
33 1
            throw new InvalidArgumentException('The Sorter class does not accept an empty $orderBy');
34
        }
35
36 8
        foreach ($orderBy as $field => $order) {
37 8
            $this->fields[] = $field;
38 8
            $this->orders[] = $this->getOrder($order);
39
        }
40 7
    }
41
42
    /**
43
     * @param mixed[] $a
44
     * @param mixed[] $b
45
     */
46 7
    public function __invoke(array $a, array $b) : int
47
    {
48 7
        $returnVal        = 0;
49 7
        $comparisonField  = $this->fields[$this->level];
50 7
        $order            = $this->orders[$this->level];
51 7
        $aComparisonField = $this->getComparisonField($a, $comparisonField);
52 6
        $bComparisonField = $this->getComparisonField($b, $comparisonField);
53
54 6
        $comparisonResult = $aComparisonField <=> $bComparisonField;
55
56 6
        if ($comparisonResult !== 0) {
57 6
            $returnVal = $comparisonResult;
58
        } else {
59 3
            if ($this->level < count($this->fields) - 1) {
60 3
                $this->level++;
61
62 3
                return $this->__invoke($a, $b);
63
            }
64
        }
65
66 6
        $returnVal *= $order;
67
68 6
        $this->level = 0;
69
70 6
        return $returnVal;
71
    }
72
73 8
    private function getOrder(string $order) : int
74
    {
75 8
        $lowercaseOrder = strtolower($order);
76
77 8
        if ($lowercaseOrder === self::ORDER_ASC) {
78 4
            return 1;
79
        }
80
81 5
        if ($lowercaseOrder === self::ORDER_DESC) {
82 4
            return -1;
83
        }
84
85 1
        throw new InvalidArgumentException(sprintf(
86 1
            '$order value of %s is not accepted. Only a value of asc or desc is allowed.',
87 1
            $order
88
        ));
89
    }
90
91
    /**
92
     * @param mixed[] $item
93
     *
94
     * @return mixed
95
     */
96 7
    private function getComparisonField(array $item, string $field)
97
    {
98 7
        if (! isset($item[$field])) {
99 1
            throw new InvalidArgumentException(sprintf('Unable to find comparison field %s', $field));
100
        }
101
102 6
        $value = $item[$field];
103
104 6
        return is_string($value) ? strtolower($value) : $value;
105
    }
106
}
107