diff options
Diffstat (limited to 'apps/weather_status/lib/Service/WeatherStatusService.php')
-rw-r--r-- | apps/weather_status/lib/Service/WeatherStatusService.php | 171 |
1 files changed, 60 insertions, 111 deletions
diff --git a/apps/weather_status/lib/Service/WeatherStatusService.php b/apps/weather_status/lib/Service/WeatherStatusService.php index fa3177b20f6..c93010e7f58 100644 --- a/apps/weather_status/lib/Service/WeatherStatusService.php +++ b/apps/weather_status/lib/Service/WeatherStatusService.php @@ -3,116 +3,55 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020, Julien Veyssier - * - * @author Julien Veyssier <eneiluj@posteo.net> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\WeatherStatus\Service; -use OCP\IConfig; -use OCP\IL10N; -use OCP\App\IAppManager; +use OCA\WeatherStatus\AppInfo\Application; +use OCA\WeatherStatus\ResponseDefinitions; use OCP\Accounts\IAccountManager; use OCP\Accounts\PropertyDoesNotExistException; -use OCP\IUserManager; -use OCP\Http\Client\IClientService; +use OCP\App\IAppManager; use OCP\Http\Client\IClient; -use OCP\ICacheFactory; +use OCP\Http\Client\IClientService; use OCP\ICache; -use OCP\ILogger; - -use OCA\WeatherStatus\AppInfo\Application; +use OCP\ICacheFactory; +use OCP\IConfig; +use OCP\IL10N; +use OCP\IUserManager; +use Psr\Log\LoggerInterface; /** * Class WeatherStatusService * * @package OCA\WeatherStatus\Service + * + * @psalm-import-type WeatherStatusForecast from ResponseDefinitions + * @psalm-import-type WeatherStatusSuccess from ResponseDefinitions + * @psalm-import-type WeatherStatusLocationWithSuccess from ResponseDefinitions + * @psalm-import-type WeatherStatusLocationWithMode from ResponseDefinitions */ class WeatherStatusService { public const MODE_BROWSER_LOCATION = 1; public const MODE_MANUAL_LOCATION = 2; - /** @var IClientService */ - private $clientService; - - /** @var IClient */ - private $client; - - /** @var IConfig */ - private $config; - - /** @var IL10N */ - private $l10n; - - /** @var ILogger */ - private $logger; - - /** @var IAccountManager */ - private $accountManager; - - /** @var IUserManager */ - private $userManager; - - /** @var IAppManager */ - private $appManager; - - /** @var ICache */ - private $cache; - - /** @var string */ - private $userId; - - /** @var string */ - private $version; - - /** - * WeatherStatusService constructor - * - * @param IClientService $clientService - * @param IConfig $config - * @param IL10N $l10n - * @param ILogger $logger - * @param IAccountManager $accountManager - * @param IUserManager $userManager - * @param IAppManager $appManager - * @param ICacheFactory $cacheFactory - * @param string $userId - */ - public function __construct(IClientService $clientService, - IConfig $config, - IL10N $l10n, - ILogger $logger, - IAccountManager $accountManager, - IUserManager $userManager, - IAppManager $appManager, - ICacheFactory $cacheFactory, - ?string $userId) { - $this->config = $config; - $this->userId = $userId; - $this->l10n = $l10n; - $this->logger = $logger; - $this->accountManager = $accountManager; - $this->userManager = $userManager; - $this->appManager = $appManager; + private IClient $client; + private ICache $cache; + private string $version; + + public function __construct( + private IClientService $clientService, + private IConfig $config, + private IL10N $l10n, + private LoggerInterface $logger, + private IAccountManager $accountManager, + private IUserManager $userManager, + private IAppManager $appManager, + private ICacheFactory $cacheFactory, + private ?string $userId, + ) { $this->version = $appManager->getAppVersion(Application::APP_ID); - $this->clientService = $clientService; $this->client = $clientService->newClient(); $this->cache = $cacheFactory->createDistributed('weatherstatus'); } @@ -122,7 +61,7 @@ class WeatherStatusService { * - ask the browser * - use the user defined address * @param int $mode New mode - * @return array success state + * @return WeatherStatusSuccess success state */ public function setMode(int $mode): array { $this->config->setUserValue($this->userId, Application::APP_ID, 'mode', strval($mode)); @@ -131,8 +70,7 @@ class WeatherStatusService { /** * Get favorites list - * @param array $favorites - * @return array success state + * @return list<string> */ public function getFavorites(): array { $favoritesJson = $this->config->getUserValue($this->userId, Application::APP_ID, 'favorites', ''); @@ -141,8 +79,8 @@ class WeatherStatusService { /** * Set favorites list - * @param array $favorites - * @return array success state + * @param list<string> $favorites + * @return WeatherStatusSuccess success state */ public function setFavorites(array $favorites): array { $this->config->setUserValue($this->userId, Application::APP_ID, 'favorites', json_encode($favorites)); @@ -152,7 +90,7 @@ class WeatherStatusService { /** * Try to use the address set in user personal settings as weather location * - * @return array with success state and address information + * @return WeatherStatusLocationWithSuccess with success state and address information */ public function usePersonalAddress(): array { $account = $this->accountManager->getAccount($this->userManager->get($this->userId)); @@ -174,7 +112,7 @@ class WeatherStatusService { * @param string|null $address Any approximative or exact address * @param float|null $lat Latitude in decimal degree format * @param float|null $lon Longitude in decimal degree format - * @return array with success state and address information + * @return WeatherStatusLocationWithSuccess with success state and address information */ public function setLocation(?string $address, ?float $lat, ?float $lon): array { if (!is_null($lat) && !is_null($lon)) { @@ -183,7 +121,7 @@ class WeatherStatusService { $this->config->setUserValue($this->userId, Application::APP_ID, 'lon', strval($lon)); // resolve and store formatted address $address = $this->resolveLocation($lat, $lon); - $address = $address ? $address : $this->l10n->t('Unknown address'); + $address = $address ?: $this->l10n->t('Unknown address'); $this->config->setUserValue($this->userId, Application::APP_ID, 'address', $address); // get and store altitude $altitude = $this->getAltitude($lat, $lon); @@ -278,7 +216,7 @@ class WeatherStatusService { * Set address and resolve it to get coordinates * * @param string $address Any approximative or exact address - * @return array with success state and address information (coordinates and formatted address) + * @return WeatherStatusLocationWithSuccess with success state and address information (coordinates and formatted address) */ public function setAddress(string $address): array { $addressInfo = $this->searchForAddress($address); @@ -306,28 +244,39 @@ class WeatherStatusService { * Ask nominatim information about an unformatted address * * @param string Unformatted address - * @return array Full Nominatim result for the given address + * @return array{display_name?: string, lat?: string, lon?: string, error?: string} Full Nominatim result for the given address */ private function searchForAddress(string $address): array { $params = [ + 'q' => $address, 'format' => 'json', 'addressdetails' => '1', 'extratags' => '1', 'namedetails' => '1', 'limit' => '1', ]; - $url = 'https://nominatim.openstreetmap.org/search/' . $address; + $url = 'https://nominatim.openstreetmap.org/search'; $results = $this->requestJSON($url, $params); - if (count($results) > 0) { - return $results[0]; + + if (isset($results['error'])) { + return ['error' => (string)$results['error']]; } + + if (count($results) > 0 && is_array($results[0])) { + return [ + 'display_name' => (string)($results[0]['display_name'] ?? null), + 'lat' => (string)($results[0]['lat'] ?? null), + 'lon' => (string)($results[0]['lon'] ?? null), + ]; + } + return ['error' => $this->l10n->t('No result.')]; } /** * Get stored user location * - * @return array which contains coordinates, formatted address and current weather status mode + * @return WeatherStatusLocationWithMode which contains coordinates, formatted address and current weather status mode */ public function getLocation(): array { $lat = $this->config->getUserValue($this->userId, Application::APP_ID, 'lat', ''); @@ -345,7 +294,7 @@ class WeatherStatusService { /** * Get forecast for current location * - * @return array which contains success state and filtered forecast data + * @return list<WeatherStatusForecast>|array{error: string}|WeatherStatusSuccess which contains success state and filtered forecast data */ public function getForecast(): array { $lat = $this->config->getUserValue($this->userId, Application::APP_ID, 'lat', ''); @@ -368,7 +317,7 @@ class WeatherStatusService { * @param float $lon Longitude of requested forecast, in decimal degree format * @param float $altitude Altitude of requested forecast, in meter * @param int $nbValues Number of forecast values (hours) - * @return array Filtered forecast data + * @return list<WeatherStatusForecast>|array{error: string} Filtered forecast data */ private function forecastRequest(float $lat, float $lon, float $altitude, int $nbValues = 10): array { $params = [ @@ -426,8 +375,8 @@ class WeatherStatusService { $cacheDuration = 60 * 60; if (isset($headers['Expires']) && count($headers['Expires']) > 0) { // if the Expires response header is set, use it to define cache duration - $expireTs = (new \Datetime($headers['Expires'][0]))->getTimestamp(); - $nowTs = (new \Datetime())->getTimestamp(); + $expireTs = (new \DateTime($headers['Expires'][0]))->getTimestamp(); + $nowTs = (new \DateTime())->getTimestamp(); $duration = $expireTs - $nowTs; if ($duration > $cacheDuration) { $cacheDuration = $duration; @@ -438,7 +387,7 @@ class WeatherStatusService { return $json; } } catch (\Exception $e) { - $this->logger->warning($url . 'API error : ' . $e, ['app' => Application::APP_ID]); + $this->logger->warning($url . ' API error : ' . $e->getMessage(), ['exception' => $e]); return ['error' => $e->getMessage()]; } } |