Completed
Push — 1.1 ( 17428c...7dea68 )
by David
10:20
created

AssetType::getValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
namespace TheCodingMachine\Discovery;
3
4
/**
5
 * An asset type is essentially an array of Assets
6
 */
7
class AssetType implements \JsonSerializable, AssetTypeInterface
8
{
9
    /**
10
     * @var string
11
     */
12
    private $name;
13
14
    /**
15
     * @var Asset[]
16
     */
17
    private $assets = [];
18
19
    private $sorted = false;
20
21
    public function __construct(string $name)
22
    {
23
        $this->name = $name;
24
    }
25
26
    /**
27
     * Registers an asset operation.
28
     * Note: it is expected that asset operations will be added in the order of package dependencies.
29
     * Order of assets with same priority will be preserved.
30
     *
31
     * @param AssetOperation $operation
32
     */
33
    public function addAssetOperation(AssetOperation $operation)
34
    {
35
        if ($operation->getOperation() === AssetOperation::ADD) {
36
            $this->assets[] = $operation->getAsset();
37
        } else {
38
            // This is a remove!
39
            $this->assets = array_values(array_filter($this->assets, function (Asset $asset) use ($operation) {
0 ignored issues
show
Documentation Bug introduced by
It seems like array_values(array_filte...sset()->getValue(); })) of type array<integer,?> is incompatible with the declared type array<integer,object<The...chine\Discovery\Asset>> of property $assets.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
40
                return $asset->getValue() !== $operation->getAsset()->getValue();
41
            }));
42
        }
43
44
        $this->sorted = false;
45
    }
46
47
    /**
48
     * Sort assets by priority.
49
     */
50
    private function sortAssets()
51
    {
52
        if ($this->sorted === true) {
53
            return;
54
        }
55
56
        // Let's order assets by priority.
57
        $this->stableSort($this->assets, function (Asset $asset1, Asset $asset2) {
58
            return $asset2->getPriority() <=> $asset1->getPriority();
59
        });
60
61
        $this->sorted = true;
62
    }
63
64
    /**
65
     * Similar to a usort except that if 2 priorities are equal, order is preserved.
66
     * Shamelessly copied from http://php.net/manual/fr/function.usort.php#38827
67
     *
68
     * @param $array
69
     * @param string $cmp_function
70
     */
71
    private function stableSort(&$array, $cmp_function = 'strcmp')
72
    {
73
        // Arrays of size < 2 require no action.
74
        if (count($array) < 2) {
75
            return;
76
        }
77
        // Split the array in half
78
        $halfway = count($array) / 2;
79
        $array1 = array_slice($array, 0, $halfway);
80
        $array2 = array_slice($array, $halfway);
81
        // Recurse to sort the two halves
82
        $this->stableSort($array1, $cmp_function);
83
        $this->stableSort($array2, $cmp_function);
84
        // If all of $array1 is <= all of $array2, just append them.
85
        if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
86
            $array = array_merge($array1, $array2);
87
            return;
88
        }
89
        // Merge the two sorted arrays into a single sorted array
90
        $array = array();
91
        $ptr1 = $ptr2 = 0;
92
        while ($ptr1 < count($array1) && $ptr2 < count($array2)) {
93
            if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
94
                $array[] = $array1[$ptr1++];
95
            } else {
96
                $array[] = $array2[$ptr2++];
97
            }
98
        }
99
        // Merge the remainder
100
        while ($ptr1 < count($array1)) {
101
            $array[] = $array1[$ptr1++];
102
        }
103
        while ($ptr2 < count($array2)) {
104
            $array[] = $array2[$ptr2++];
105
        }
106
    }
107
108
    /**
109
     * @return string
110
     */
111
    public function getName(): string
112
    {
113
        return $this->name;
114
    }
115
116
    /**
117
     * @return Asset[]
118
     */
119
    public function getAssets() : array
120
    {
121
        $this->sortAssets();
122
        return $this->assets;
123
    }
124
125
    /**
126
     * Shortcut to get an array of values of the assets.
127
     *
128
     * @return string[]
129
     */
130
    public function getValues() : array
131
    {
132
        return array_map(function (Asset $asset) {
133
            return $asset->getValue();
134
        }, $this->getAssets());
135
    }
136
137
    /**
138
     * Specify data which should be serialized to JSON
139
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
140
     * @return mixed data which can be serialized by <b>json_encode</b>,
141
     * which is a value of any type other than a resource.
142
     * @since 5.4.0
143
     */
144
    public function jsonSerialize()
145
    {
146
        return array_map(function (Asset $asset) {
147
            return $asset->jsonSerialize();
148
        }, $this->getAssets());
149
    }
150
}
151