PackageFilter   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Test Coverage

Coverage 98.48%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 56
c 5
b 0
f 0
dl 0
loc 180
ccs 65
cts 66
cp 0.9848
rs 10
wmc 30

12 Methods

Rating   Name   Duplication   Size   Complexity  
A setOldVersionFilter() 0 3 1
A __construct() 0 4 1
A isMatchingArchitecture() 0 7 2
A setChannelFilter() 0 3 1
A setFirmwareVersionFilter() 0 3 1
A setArchitectureFilter() 0 10 2
A isMatchingFirmwareVersion() 0 8 3
A removeObsoleteVersions() 0 11 4
A isMatchingChannel() 0 11 5
A isMatchingFirmwareVersionPre7() 0 5 2
A getFilteredPackageList() 0 20 6
A isMatchingFirmwareVersionPost7() 0 5 2
1
<?php
2
3
namespace SSpkS\Package;
4
5
use \SSpkS\Device\DeviceList;
0 ignored issues
show
Bug introduced by
The type \SSpkS\Device\DeviceList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use \SSpkS\Package\Package;
0 ignored issues
show
Bug introduced by
The type \SSpkS\Package\Package was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
This use statement conflicts with another class in this namespace, SSpkS\Package\Package. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
8
/**
9
 * SPK PackageFinder class
10
 */
11
class PackageFilter
12
{
13
    private $config;
14
    private $pkgList;
15
    /** @var bool|string[] $filterArch Array of allowed architectures, or FALSE to ignore. */
16
    private $filterArch = false;
17
    /** @var bool|string $filterFwVersion Target firmware version, or FALSE to ignore. */
18
    private $filterFwVersion = false;
19
    /** @var bool|string $filterChannel Channel 'stable' or 'beta', or FALSE to ignore. */
20
    private $filterChannel = false;
21
    /** @var bool $filterOldVersions TRUE to return unique packages with latest version only. */
22
    private $filterOldVersions = false;
23
24
    /**
25
     * @param \SSpkS\Config $config Config object
26
     * @param \SSpkS\Package\Package[] $pkgList List of Package objects to filter
27
     */
28 5
    public function __construct(\SSpkS\Config $config, array $pkgList)
29
    {
30 5
        $this->config = $config;
31 5
        $this->pkgList = $pkgList;
32 5
    }
33
34
    /**
35
     * Sets the architecture to filter for.
36
     *
37
     * @param string $arch Architecture.
38
     */
39 1
    public function setArchitectureFilter($arch)
40
    {
41
        // Specific corner case
42 1
        if ($arch == '88f6282') {
43
            $arch = '88f6281';
44
        }
45
      
46 1
        $dl = new DeviceList($this->config);
47 1
        $family = $dl->getFamily($arch);
48 1
        $this->filterArch = array_unique(array('noarch', $arch, $family));
49 1
    }
50
51
    /**
52
     * Sets the firmware version to filter for.
53
     *
54
     * @param string|bool $version Firmware version in dotted notation ('1.2.3456') or FALSE to ignore.
55
     */
56 1
    public function setFirmwareVersionFilter($version)
57
    {
58 1
        $this->filterFwVersion = $version;
59 1
    }
60
61
    /**
62
     * Sets the channel to filter for.
63
     *
64
     * @param string $channel Channel ('stable' or 'beta')
65
     */
66 1
    public function setChannelFilter($channel)
67
    {
68 1
        $this->filterChannel = $channel;
69 1
    }
70
71
    /**
72
     * Enables or disables omitting older versions of the same package from the result set.
73
     *
74
     * @param bool $status TRUE to enable the filter, FALSE to disable.
75
     */
76 1
    public function setOldVersionFilter($status)
77
    {
78 1
        $this->filterOldVersions = $status;
79 1
    }
80
81
    /**
82
     * If filter is enabled, checks if architecture of $package is compatible to requested one.
83
     *
84
     * @param \SSpkS\Package\Package $package Package to test.
85
     * @return bool TRUE if matching, or FALSE.
86
     */
87 5
    public function isMatchingArchitecture($package)
88
    {
89 5
        if ($this->filterArch === false) {
90 4
            return true;
91
        }
92 1
        $matches = array_intersect(/** @scrutinizer ignore-type */ $this->filterArch, $package->arch);
93 1
        return (count($matches) > 0);
94
    }
95
96
    /**
97
     * If filter is enabled, checks if minimal firmware required of $package is
98
     * smaller or equal to system firmware.
99
     *
100
     * @param \SSpkS\Package\Package $package Package to test.
101
     * @return bool TRUE if matching, or FALSE.
102
     */
103 5
    public function isMatchingFirmwareVersion(\SSpkS\Package\Package $package): bool
104
    {
105 5
        if ($this->filterFwVersion === false) {
106 4
            return true;
107
        }
108 1
        if(version_compare(/** @scrutinizer ignore-type */ $this->filterFwVersion, '7', '<'))
109 1
            return $this->isMatchingFirmwareVersionPre7($package);
110 1
        return $this->isMatchingFirmwareVersionPost7($package);
111
    }
112
113 1
    private function isMatchingFirmwareVersionPre7(\SSpkS\Package\Package $package): bool
114
    {
115
        // on DSM6 or less, package must be <= to filter
116 1
        return version_compare($package->firmware, /** @scrutinizer ignore-type */ '7', '<')
117 1
        && version_compare($package->firmware, /** @scrutinizer ignore-type */ $this->filterFwVersion, '<=');
118
    }
119
120 1
    private function isMatchingFirmwareVersionPost7(\SSpkS\Package\Package $package): bool
121
    {
122
        // on DSM7 or above (hypothetically), package must be <= to filter
123 1
        return version_compare($package->firmware, /** @scrutinizer ignore-type */ '7', '>=')
124 1
        && version_compare($package->firmware, /** @scrutinizer ignore-type */ $this->filterFwVersion, '<=');
125
    }
126
127
    /**
128
     * If filter is enabled, checks if channel of $package matches requested one.
129
     * 'beta' will show ALL packages, also those from 'stable'.
130
     *
131
     * @param \SSpkS\Package\Package $package Package to test.
132
     * @return bool TRUE if matching, or FALSE.
133
     */
134 5
    public function isMatchingChannel($package)
135
    {
136 5
        if ($this->filterChannel === false) {
137 4
            return true;
138
        }
139 1
        if ($this->filterChannel == 'stable' && $package->isBeta() === false) {
140 1
            return true;
141 1
        } elseif ($this->filterChannel == 'beta') {
142 1
            return true;
143
        }
144 1
        return false;
145
    }
146
147
    /**
148
     * Removes older versions of same package from $pkgList.
149
     *
150
     * @param \SSpkS\Package\Package[] $pkgList List of packages
151
     * @return \SSpkS\Package\Package[] List of unique packages
152
     */
153 1
    public function removeObsoleteVersions($pkgList)
154
    {
155 1
        $uniqueList = array();
156 1
        foreach ($pkgList as $package) {
157 1
            $pkgId = $package->package;
158 1
            if (isset($uniqueList[$pkgId]) && version_compare($uniqueList[$pkgId]->version, $package->version, '>=')) {
159 1
                continue;
160
            }
161 1
            $uniqueList[$pkgId] = $package;
162
        }
163 1
        return array_values($uniqueList);
164
    }
165
166
    /**
167
     * Returns the list of packages matching the currently set filters.
168
     *
169
     * @return \SSpkS\Package\Package[] List of Package objects matching filters.
170
     */
171 5
    public function getFilteredPackageList()
172
    {
173 5
        $filteredPackages = array();
174 5
        foreach ($this->pkgList as $package) {
175 5
            if (!$this->isMatchingArchitecture($package)) {
176 1
                continue;
177
            }
178 5
            if (!$this->isMatchingFirmwareVersion($package)) {
179 1
                continue;
180
            }
181 5
            if (!$this->isMatchingChannel($package)) {
182 1
                continue;
183
            }
184 5
            $filteredPackages[] = $package;
185
        }
186 5
        if ($this->filterOldVersions) {
187
            // remove older versions of duplicate packages from $filteredPackages
188 1
            $filteredPackages = $this->removeObsoleteVersions($filteredPackages);
189
        }
190 5
        return $filteredPackages;
191
    }
192
}
193