Completed
Push — master ( 922271...29832a )
by
unknown
21:06
created
lib/private/App/AppStore/Fetcher/Fetcher.php 2 patches
Indentation   +206 added lines, -206 removed lines patch added patch discarded remove patch
@@ -22,210 +22,210 @@
 block discarded – undo
22 22
 use Psr\Log\LoggerInterface;
23 23
 
24 24
 abstract class Fetcher {
25
-	public const INVALIDATE_AFTER_SECONDS = 3600;
26
-	public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900;
27
-	public const RETRY_AFTER_FAILURE_SECONDS = 300;
28
-	public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1';
29
-
30
-	/** @var IAppData */
31
-	protected $appData;
32
-
33
-	/** @var string */
34
-	protected $fileName;
35
-	/** @var string */
36
-	protected $endpointName;
37
-	/** @var ?string */
38
-	protected $version = null;
39
-	/** @var ?string */
40
-	protected $channel = null;
41
-
42
-	public function __construct(
43
-		Factory $appDataFactory,
44
-		protected IClientService $clientService,
45
-		protected ITimeFactory $timeFactory,
46
-		protected IConfig $config,
47
-		protected LoggerInterface $logger,
48
-		protected IRegistry $registry,
49
-	) {
50
-		$this->appData = $appDataFactory->get('appstore');
51
-	}
52
-
53
-	/**
54
-	 * Fetches the response from the server
55
-	 *
56
-	 * @param string $ETag
57
-	 * @param string $content
58
-	 *
59
-	 * @return array
60
-	 */
61
-	protected function fetch($ETag, $content, $allowUnstable = false) {
62
-		$appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
63
-		if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) {
64
-			return [];
65
-		}
66
-
67
-		if (!$appstoreenabled) {
68
-			return [];
69
-		}
70
-
71
-		$options = [
72
-			'timeout' => 60,
73
-		];
74
-
75
-		if ($ETag !== '') {
76
-			$options['headers'] = [
77
-				'If-None-Match' => $ETag,
78
-			];
79
-		}
80
-
81
-		if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) {
82
-			// If we have a valid subscription key, send it to the appstore
83
-			$subscriptionKey = $this->config->getAppValue('support', 'subscription_key');
84
-			if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) {
85
-				$options['headers'] ??= [];
86
-				$options['headers']['X-NC-Subscription-Key'] = $subscriptionKey;
87
-			}
88
-		}
89
-
90
-		$client = $this->clientService->newClient();
91
-		try {
92
-			$response = $client->get($this->getEndpoint(), $options);
93
-		} catch (ConnectException|ClientException|ServerException $e) {
94
-			$this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time());
95
-			$this->logger->error('Failed to connect to the app store', ['exception' => $e]);
96
-			return [];
97
-		}
98
-
99
-		$responseJson = [];
100
-		if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) {
101
-			$responseJson['data'] = json_decode($content, true);
102
-		} else {
103
-			$responseJson['data'] = json_decode($response->getBody(), true);
104
-			$ETag = $response->getHeader('ETag');
105
-		}
106
-		$this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure');
107
-
108
-		$responseJson['timestamp'] = $this->timeFactory->getTime();
109
-		$responseJson['ncversion'] = $this->getVersion();
110
-		if ($ETag !== '') {
111
-			$responseJson['ETag'] = $ETag;
112
-		}
113
-
114
-		return $responseJson;
115
-	}
116
-
117
-	/**
118
-	 * Returns the array with the entries on the appstore server
119
-	 *
120
-	 * @param bool [$allowUnstable] Allow unstable releases
121
-	 * @return array
122
-	 */
123
-	public function get($allowUnstable = false) {
124
-		$appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
125
-		$internetavailable = $this->config->getSystemValueBool('has_internet_connection', true);
126
-		$isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL;
127
-
128
-		if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) {
129
-			$this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']);
130
-			return [];
131
-		}
132
-
133
-		$rootFolder = $this->appData->getFolder('/');
134
-
135
-		$ETag = '';
136
-		$content = '';
137
-
138
-		try {
139
-			// File does already exists
140
-			$file = $rootFolder->getFile($this->fileName);
141
-			$jsonBlob = json_decode($file->getContent(), true);
142
-
143
-			if (is_array($jsonBlob)) {
144
-				// No caching when the version has been updated
145
-				if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) {
146
-					// If the timestamp is older than 3600 seconds request the files new
147
-					$invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS;
148
-
149
-					if ($allowUnstable) {
150
-						$invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE;
151
-					}
152
-
153
-					if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) {
154
-						return $jsonBlob['data'];
155
-					}
156
-
157
-					if (isset($jsonBlob['ETag'])) {
158
-						$ETag = $jsonBlob['ETag'];
159
-						$content = json_encode($jsonBlob['data']);
160
-					}
161
-				}
162
-			}
163
-		} catch (NotFoundException $e) {
164
-			// File does not already exists
165
-			$file = $rootFolder->newFile($this->fileName);
166
-		}
167
-
168
-		// Refresh the file content
169
-		try {
170
-			$responseJson = $this->fetch($ETag, $content, $allowUnstable);
171
-
172
-			if (empty($responseJson) || empty($responseJson['data'])) {
173
-				return [];
174
-			}
175
-
176
-			$file->putContent(json_encode($responseJson));
177
-			return json_decode($file->getContent(), true)['data'];
178
-		} catch (ConnectException $e) {
179
-			$this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']);
180
-			return [];
181
-		} catch (\Exception $e) {
182
-			$this->logger->warning($e->getMessage(), [
183
-				'exception' => $e,
184
-				'app' => 'appstoreFetcher',
185
-			]);
186
-			return [];
187
-		}
188
-	}
189
-
190
-	/**
191
-	 * Get the currently Nextcloud version
192
-	 * @return string
193
-	 */
194
-	protected function getVersion() {
195
-		if ($this->version === null) {
196
-			$this->version = $this->config->getSystemValueString('version', '0.0.0');
197
-		}
198
-		return $this->version;
199
-	}
200
-
201
-	/**
202
-	 * Set the current Nextcloud version
203
-	 * @param string $version
204
-	 */
205
-	public function setVersion(string $version) {
206
-		$this->version = $version;
207
-	}
208
-
209
-	/**
210
-	 * Get the currently Nextcloud update channel
211
-	 * @return string
212
-	 */
213
-	protected function getChannel() {
214
-		if ($this->channel === null) {
215
-			$this->channel = Server::get(ServerVersion::class)->getChannel();
216
-		}
217
-		return $this->channel;
218
-	}
219
-
220
-	/**
221
-	 * Set the current Nextcloud update channel
222
-	 * @param string $channel
223
-	 */
224
-	public function setChannel(string $channel) {
225
-		$this->channel = $channel;
226
-	}
227
-
228
-	protected function getEndpoint(): string {
229
-		return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName;
230
-	}
25
+    public const INVALIDATE_AFTER_SECONDS = 3600;
26
+    public const INVALIDATE_AFTER_SECONDS_UNSTABLE = 900;
27
+    public const RETRY_AFTER_FAILURE_SECONDS = 300;
28
+    public const APP_STORE_URL = 'https://apps.nextcloud.com/api/v1';
29
+
30
+    /** @var IAppData */
31
+    protected $appData;
32
+
33
+    /** @var string */
34
+    protected $fileName;
35
+    /** @var string */
36
+    protected $endpointName;
37
+    /** @var ?string */
38
+    protected $version = null;
39
+    /** @var ?string */
40
+    protected $channel = null;
41
+
42
+    public function __construct(
43
+        Factory $appDataFactory,
44
+        protected IClientService $clientService,
45
+        protected ITimeFactory $timeFactory,
46
+        protected IConfig $config,
47
+        protected LoggerInterface $logger,
48
+        protected IRegistry $registry,
49
+    ) {
50
+        $this->appData = $appDataFactory->get('appstore');
51
+    }
52
+
53
+    /**
54
+     * Fetches the response from the server
55
+     *
56
+     * @param string $ETag
57
+     * @param string $content
58
+     *
59
+     * @return array
60
+     */
61
+    protected function fetch($ETag, $content, $allowUnstable = false) {
62
+        $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
63
+        if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) {
64
+            return [];
65
+        }
66
+
67
+        if (!$appstoreenabled) {
68
+            return [];
69
+        }
70
+
71
+        $options = [
72
+            'timeout' => 60,
73
+        ];
74
+
75
+        if ($ETag !== '') {
76
+            $options['headers'] = [
77
+                'If-None-Match' => $ETag,
78
+            ];
79
+        }
80
+
81
+        if ($this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL) {
82
+            // If we have a valid subscription key, send it to the appstore
83
+            $subscriptionKey = $this->config->getAppValue('support', 'subscription_key');
84
+            if ($this->registry->delegateHasValidSubscription() && $subscriptionKey) {
85
+                $options['headers'] ??= [];
86
+                $options['headers']['X-NC-Subscription-Key'] = $subscriptionKey;
87
+            }
88
+        }
89
+
90
+        $client = $this->clientService->newClient();
91
+        try {
92
+            $response = $client->get($this->getEndpoint(), $options);
93
+        } catch (ConnectException|ClientException|ServerException $e) {
94
+            $this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time());
95
+            $this->logger->error('Failed to connect to the app store', ['exception' => $e]);
96
+            return [];
97
+        }
98
+
99
+        $responseJson = [];
100
+        if ($response->getStatusCode() === Http::STATUS_NOT_MODIFIED) {
101
+            $responseJson['data'] = json_decode($content, true);
102
+        } else {
103
+            $responseJson['data'] = json_decode($response->getBody(), true);
104
+            $ETag = $response->getHeader('ETag');
105
+        }
106
+        $this->config->deleteAppValue('settings', 'appstore-fetcher-lastFailure');
107
+
108
+        $responseJson['timestamp'] = $this->timeFactory->getTime();
109
+        $responseJson['ncversion'] = $this->getVersion();
110
+        if ($ETag !== '') {
111
+            $responseJson['ETag'] = $ETag;
112
+        }
113
+
114
+        return $responseJson;
115
+    }
116
+
117
+    /**
118
+     * Returns the array with the entries on the appstore server
119
+     *
120
+     * @param bool [$allowUnstable] Allow unstable releases
121
+     * @return array
122
+     */
123
+    public function get($allowUnstable = false) {
124
+        $appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
125
+        $internetavailable = $this->config->getSystemValueBool('has_internet_connection', true);
126
+        $isDefaultAppStore = $this->config->getSystemValueString('appstoreurl', self::APP_STORE_URL) === self::APP_STORE_URL;
127
+
128
+        if (!$appstoreenabled || (!$internetavailable && $isDefaultAppStore)) {
129
+            $this->logger->info('AppStore is disabled or this instance has no Internet connection to access the default app store', ['app' => 'appstoreFetcher']);
130
+            return [];
131
+        }
132
+
133
+        $rootFolder = $this->appData->getFolder('/');
134
+
135
+        $ETag = '';
136
+        $content = '';
137
+
138
+        try {
139
+            // File does already exists
140
+            $file = $rootFolder->getFile($this->fileName);
141
+            $jsonBlob = json_decode($file->getContent(), true);
142
+
143
+            if (is_array($jsonBlob)) {
144
+                // No caching when the version has been updated
145
+                if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) {
146
+                    // If the timestamp is older than 3600 seconds request the files new
147
+                    $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS;
148
+
149
+                    if ($allowUnstable) {
150
+                        $invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE;
151
+                    }
152
+
153
+                    if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) {
154
+                        return $jsonBlob['data'];
155
+                    }
156
+
157
+                    if (isset($jsonBlob['ETag'])) {
158
+                        $ETag = $jsonBlob['ETag'];
159
+                        $content = json_encode($jsonBlob['data']);
160
+                    }
161
+                }
162
+            }
163
+        } catch (NotFoundException $e) {
164
+            // File does not already exists
165
+            $file = $rootFolder->newFile($this->fileName);
166
+        }
167
+
168
+        // Refresh the file content
169
+        try {
170
+            $responseJson = $this->fetch($ETag, $content, $allowUnstable);
171
+
172
+            if (empty($responseJson) || empty($responseJson['data'])) {
173
+                return [];
174
+            }
175
+
176
+            $file->putContent(json_encode($responseJson));
177
+            return json_decode($file->getContent(), true)['data'];
178
+        } catch (ConnectException $e) {
179
+            $this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']);
180
+            return [];
181
+        } catch (\Exception $e) {
182
+            $this->logger->warning($e->getMessage(), [
183
+                'exception' => $e,
184
+                'app' => 'appstoreFetcher',
185
+            ]);
186
+            return [];
187
+        }
188
+    }
189
+
190
+    /**
191
+     * Get the currently Nextcloud version
192
+     * @return string
193
+     */
194
+    protected function getVersion() {
195
+        if ($this->version === null) {
196
+            $this->version = $this->config->getSystemValueString('version', '0.0.0');
197
+        }
198
+        return $this->version;
199
+    }
200
+
201
+    /**
202
+     * Set the current Nextcloud version
203
+     * @param string $version
204
+     */
205
+    public function setVersion(string $version) {
206
+        $this->version = $version;
207
+    }
208
+
209
+    /**
210
+     * Get the currently Nextcloud update channel
211
+     * @return string
212
+     */
213
+    protected function getChannel() {
214
+        if ($this->channel === null) {
215
+            $this->channel = Server::get(ServerVersion::class)->getChannel();
216
+        }
217
+        return $this->channel;
218
+    }
219
+
220
+    /**
221
+     * Set the current Nextcloud update channel
222
+     * @param string $channel
223
+     */
224
+    public function setChannel(string $channel) {
225
+        $this->channel = $channel;
226
+    }
227
+
228
+    protected function getEndpoint(): string {
229
+        return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName;
230
+    }
231 231
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
 	 */
61 61
 	protected function fetch($ETag, $content, $allowUnstable = false) {
62 62
 		$appstoreenabled = $this->config->getSystemValueBool('appstoreenabled', true);
63
-		if ((int)$this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) {
63
+		if ((int) $this->config->getAppValue('settings', 'appstore-fetcher-lastFailure', '0') > time() - self::RETRY_AFTER_FAILURE_SECONDS) {
64 64
 			return [];
65 65
 		}
66 66
 
@@ -90,8 +90,8 @@  discard block
 block discarded – undo
90 90
 		$client = $this->clientService->newClient();
91 91
 		try {
92 92
 			$response = $client->get($this->getEndpoint(), $options);
93
-		} catch (ConnectException|ClientException|ServerException $e) {
94
-			$this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string)time());
93
+		} catch (ConnectException | ClientException | ServerException $e) {
94
+			$this->config->setAppValue('settings', 'appstore-fetcher-lastFailure', (string) time());
95 95
 			$this->logger->error('Failed to connect to the app store', ['exception' => $e]);
96 96
 			return [];
97 97
 		}
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
 						$invalidateAfterSeconds = self::INVALIDATE_AFTER_SECONDS_UNSTABLE;
151 151
 					}
152 152
 
153
-					if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) {
153
+					if ((int) $jsonBlob['timestamp'] > ($this->timeFactory->getTime() - $invalidateAfterSeconds)) {
154 154
 						return $jsonBlob['data'];
155 155
 					}
156 156
 
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 			$file->putContent(json_encode($responseJson));
177 177
 			return json_decode($file->getContent(), true)['data'];
178 178
 		} catch (ConnectException $e) {
179
-			$this->logger->warning('Could not connect to appstore: ' . $e->getMessage(), ['app' => 'appstoreFetcher']);
179
+			$this->logger->warning('Could not connect to appstore: '.$e->getMessage(), ['app' => 'appstoreFetcher']);
180 180
 			return [];
181 181
 		} catch (\Exception $e) {
182 182
 			$this->logger->warning($e->getMessage(), [
@@ -226,6 +226,6 @@  discard block
 block discarded – undo
226 226
 	}
227 227
 
228 228
 	protected function getEndpoint(): string {
229
-		return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1') . '/' . $this->endpointName;
229
+		return $this->config->getSystemValueString('appstoreurl', 'https://apps.nextcloud.com/api/v1').'/'.$this->endpointName;
230 230
 	}
231 231
 }
Please login to merge, or discard this patch.