Passed
Push — master ( 0559b6...302c10 )
by Morris
11:14 queued 10s
created

AppFetcher::fetch()   F

Complexity

Conditions 18
Paths 254

Size

Total Lines 59
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 36
nc 254
nop 2
dl 0
loc 59
rs 3.3583
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Lukas Reschke <[email protected]>
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 *
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OC\App\AppStore\Fetcher;
28
29
use OC\App\AppStore\Version\VersionParser;
30
use OC\App\CompareVersion;
31
use OC\Files\AppData\Factory;
32
use OCP\AppFramework\Utility\ITimeFactory;
33
use OCP\Http\Client\IClientService;
34
use OCP\IConfig;
35
use OCP\ILogger;
36
use OCP\Util;
37
38
class AppFetcher extends Fetcher {
39
40
	/** @var CompareVersion */
41
	private $compareVersion;
42
43
	/** @var bool */
44
	private $ignoreMaxVersion;
45
46
	/**
47
	 * @param Factory $appDataFactory
48
	 * @param IClientService $clientService
49
	 * @param ITimeFactory $timeFactory
50
	 * @param IConfig $config
51
	 * @param CompareVersion $compareVersion
52
	 * @param ILogger $logger
53
	 */
54
	public function __construct(Factory $appDataFactory,
55
								IClientService $clientService,
56
								ITimeFactory $timeFactory,
57
								IConfig $config,
58
								CompareVersion $compareVersion,
59
								ILogger $logger) {
60
		parent::__construct(
61
			$appDataFactory,
62
			$clientService,
63
			$timeFactory,
64
			$config,
65
			$logger
66
		);
67
68
		$this->fileName = 'apps.json';
69
		$this->setEndpoint();
70
		$this->compareVersion = $compareVersion;
71
		$this->ignoreMaxVersion = true;
72
	}
73
74
	/**
75
	 * Only returns the latest compatible app release in the releases array
76
	 *
77
	 * @param string $ETag
78
	 * @param string $content
79
	 *
80
	 * @return array
81
	 */
82
	protected function fetch($ETag, $content) {
83
		/** @var mixed[] $response */
84
		$response = parent::fetch($ETag, $content);
85
86
		$allowPreReleases = $this->getChannel() === 'beta' || $this->getChannel() === 'daily';
87
		$allowNightly = $this->getChannel() === 'daily';
88
89
		foreach($response['data'] as $dataKey => $app) {
90
			$releases = [];
91
92
			// Filter all compatible releases
93
			foreach($app['releases'] as $release) {
94
				// Exclude all nightly and pre-releases if required
95
				if (($allowNightly || $release['isNightly'] === false)
96
					&& ($allowPreReleases || strpos($release['version'], '-') === false)) {
97
					// Exclude all versions not compatible with the current version
98
					try {
99
						$versionParser = new VersionParser();
100
						$version = $versionParser->getVersion($release['rawPlatformVersionSpec']);
101
						$ncVersion = $this->getVersion();
102
						$min = $version->getMinimumVersion();
103
						$max = $version->getMaximumVersion();
104
						$minFulfilled = $this->compareVersion->isCompatible($ncVersion, $min, '>=');
105
						$maxFulfilled = $max !== '' &&
106
							$this->compareVersion->isCompatible($ncVersion, $max, '<=');
107
						if ($minFulfilled && ($this->ignoreMaxVersion || $maxFulfilled)) {
108
							$releases[] = $release;
109
						}
110
					} catch (\InvalidArgumentException $e) {
111
						$this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => ILogger::WARN]);
112
					}
113
				}
114
			}
115
116
			if (empty($releases)) {
117
				// Remove apps that don't have a matching release
118
				continue;
119
			}
120
121
			// Get the highest version
122
			$versions = [];
123
			foreach($releases as $release) {
124
				$versions[] = $release['version'];
125
			}
126
			usort($versions, 'version_compare');
127
			$versions = array_reverse($versions);
128
			if(isset($versions[0])) {
129
				$highestVersion = $versions[0];
130
				foreach ($releases as $release) {
131
					if ((string)$release['version'] === (string)$highestVersion) {
132
						$response['data'][$dataKey]['releases'] = [$release];
133
						break;
134
					}
135
				}
136
			}
137
		}
138
139
		$response['data'] = array_values($response['data']);
140
		return $response;
141
	}
142
143
	private function setEndpoint() {
144
		$this->endpointUrl = 'https://apps.nextcloud.com/api/v1/apps.json';
145
	}
146
147
	/**
148
	 * @param string $version
149
	 * @param string $fileName
150
	 * @param bool $ignoreMaxVersion
151
	 */
152
	public function setVersion(string $version, string $fileName = 'apps.json', bool $ignoreMaxVersion = true) {
153
		parent::setVersion($version);
154
		$this->fileName = $fileName;
155
		$this->ignoreMaxVersion = $ignoreMaxVersion;
156
		$this->setEndpoint();
157
	}
158
}
159