Completed
Push — master ( ea5a34...71c7d4 )
by Jesse
10:27
created

Sorter::sortThe()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stratadox\Sorting;
6
7
use Closure;
8
9
/**
10
 * Sorter logic for comparing multiple values according to the sort definition.
11
 *
12
 * Leaves retrieving the values to the concrete implementations.
13
 *
14
 * @author Stratadox
15
 * @package Stratadox\Sorting
16
 */
17
abstract class Sorter implements SortsTheElements
18
{
19
    public function sortThe($elements, DefinesHowToSort $sorting) : array
20
    {
21
        usort($elements, $this->function($sorting));
22
        return $elements;
23
    }
24
25
    private function function(DefinesHowToSort $sorting) : Closure
26
    {
27
        return function($element1, $element2) use ($sorting) {
28
            return $this->doTheSorting($element1, $element2, $sorting);
29
        };
30
    }
31
32
    private function doTheSorting(
33
        $element1,
34
        $element2,
35
        DefinesHowToSort $sorting
36
    ) : int
37
    {
38
        $comparison = 0;
39
        while ($sorting->isRequired()) {
40
            $comparison = $this->compareElements($element1, $element2, $sorting);
41
            if ($comparison !== 0) {
42
                break;
43
            }
44
            $sorting = $sorting->next();
45
        }
46
        return $comparison;
47
    }
48
49
    private function compareElements(
50
        $element1,
51
        $element2,
52
        DefinesHowToSort $sorting
53
    ) : int
54
    {
55
        if ($sorting->ascends()) {
56
            return $this->compareValues(
57
                $this->valueFor($element1, $sorting->field()),
58
                $this->valueFor($element2, $sorting->field())
59
            );
60
        }
61
        return $this->compareValues(
62
            $this->valueFor($element2, $sorting->field()),
63
            $this->valueFor($element1, $sorting->field())
64
        );
65
    }
66
67
    private function compareValues($value1, $value2) : int
68
    {
69
        return $value1 <=> $value2;
70
    }
71
72
    abstract protected function valueFor($element, string $field);
73
}
74