aboutsummaryrefslogtreecommitdiffstats
path: root/apps/weather_status/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/weather_status/lib')
-rw-r--r--apps/weather_status/lib/AppInfo/Application.php33
-rw-r--r--apps/weather_status/lib/Capabilities.php27
-rw-r--r--apps/weather_status/lib/Controller/WeatherStatusController.php107
-rw-r--r--apps/weather_status/lib/Listeners/BeforeTemplateRenderedListener.php38
-rw-r--r--apps/weather_status/lib/ResponseDefinitions.php72
-rw-r--r--apps/weather_status/lib/Service/WeatherStatusService.php171
6 files changed, 227 insertions, 221 deletions
diff --git a/apps/weather_status/lib/AppInfo/Application.php b/apps/weather_status/lib/AppInfo/Application.php
index e6f40321b3c..147d69ee543 100644
--- a/apps/weather_status/lib/AppInfo/Application.php
+++ b/apps/weather_status/lib/AppInfo/Application.php
@@ -3,37 +3,18 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Julien Veyssier
- *
- * @author Julien Veyssier <eneiluj@posteo.net>
- *
- * @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\AppInfo;
use OCA\WeatherStatus\Capabilities;
+use OCA\WeatherStatus\Listeners\BeforeTemplateRenderedListener;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
-use OCP\Dashboard\RegisterWidgetEvent;
-use OCP\EventDispatcher\IEventDispatcher;
-use OCP\EventDispatcher\Event;
-use OCP\Util;
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
/**
* Class Application
@@ -52,11 +33,6 @@ class Application extends App implements IBootstrap {
*/
public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);
-
- $dispatcher = $this->getContainer()->query(IEventDispatcher::class);
- $dispatcher->addListener(RegisterWidgetEvent::class, function (Event $e) {
- Util::addScript(self::APP_ID, 'weather-status');
- });
}
/**
@@ -65,6 +41,7 @@ class Application extends App implements IBootstrap {
public function register(IRegistrationContext $context): void {
// Register OCS Capabilities
$context->registerCapability(Capabilities::class);
+ $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
}
public function boot(IBootContext $context): void {
diff --git a/apps/weather_status/lib/Capabilities.php b/apps/weather_status/lib/Capabilities.php
index c9de0039a39..953b40036f3 100644
--- a/apps/weather_status/lib/Capabilities.php
+++ b/apps/weather_status/lib/Capabilities.php
@@ -3,32 +3,15 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Julien Veyssier
- *
- * @author Julien Veyssier <eneiluj@posteo.net>
- *
- * @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;
-use OCP\Capabilities\ICapability;
-
use OCA\WeatherStatus\AppInfo\Application;
+use OCP\Capabilities\ICapability;
+
/**
* Class Capabilities
*
@@ -44,7 +27,7 @@ class Capabilities implements ICapability {
}
/**
- * @inheritDoc
+ * @return array{weather_status: array{enabled: bool}}
*/
public function getCapabilities() {
return [
diff --git a/apps/weather_status/lib/Controller/WeatherStatusController.php b/apps/weather_status/lib/Controller/WeatherStatusController.php
index 01bdf78f410..c56ea3b97b3 100644
--- a/apps/weather_status/lib/Controller/WeatherStatusController.php
+++ b/apps/weather_status/lib/Controller/WeatherStatusController.php
@@ -3,117 +3,102 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2020, Julien Veyssier
- *
- * @author Julien Veyssier <eneiluj@posteo.net>
- *
- * @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\Controller;
+use OCA\WeatherStatus\ResponseDefinitions;
use OCA\WeatherStatus\Service\WeatherStatusService;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
-use OCP\ILogger;
use OCP\IRequest;
+/**
+ * @psalm-import-type WeatherStatusForecast from ResponseDefinitions
+ * @psalm-import-type WeatherStatusSuccess from ResponseDefinitions
+ * @psalm-import-type WeatherStatusLocation from ResponseDefinitions
+ * @psalm-import-type WeatherStatusLocationWithSuccess from ResponseDefinitions
+ * @psalm-import-type WeatherStatusLocationWithMode from ResponseDefinitions
+ */
class WeatherStatusController extends OCSController {
-
- /** @var string */
- private $userId;
-
- /** @var ILogger */
- private $logger;
-
- /** @var WeatherStatusService */
- private $service;
-
- public function __construct(string $appName,
- IRequest $request,
- ILogger $logger,
- WeatherStatusService $service,
- ?string $userId) {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private WeatherStatusService $service,
+ private ?string $userId,
+ ) {
parent::__construct($appName, $request);
- $this->userId = $userId;
- $this->logger = $logger;
- $this->service = $service;
}
/**
- * @NoAdminRequired
- *
* Try to use the address set in user personal settings as weather location
*
- * @return DataResponse with success state and address information
+ * @return DataResponse<Http::STATUS_OK, WeatherStatusLocationWithSuccess, array{}>
+ *
+ * 200: Address updated
*/
+ #[NoAdminRequired]
public function usePersonalAddress(): DataResponse {
return new DataResponse($this->service->usePersonalAddress());
}
/**
- * @NoAdminRequired
- *
* Change the weather status mode. There are currently 2 modes:
* - ask the browser
* - use the user defined address
*
* @param int $mode New mode
- * @return DataResponse success state
+ * @return DataResponse<Http::STATUS_OK, WeatherStatusSuccess, array{}>
+ *
+ * 200: Weather status mode updated
*/
+ #[NoAdminRequired]
public function setMode(int $mode): DataResponse {
return new DataResponse($this->service->setMode($mode));
}
/**
- * @NoAdminRequired
- *
* Set address and resolve it to get coordinates
* or directly set coordinates and get address with reverse geocoding
*
* @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 DataResponse with success state and address information
+ * @return DataResponse<Http::STATUS_OK, WeatherStatusLocationWithSuccess, array{}>
+ *
+ * 200: Location updated
*/
+ #[NoAdminRequired]
public function setLocation(?string $address, ?float $lat, ?float $lon): DataResponse {
$currentWeather = $this->service->setLocation($address, $lat, $lon);
return new DataResponse($currentWeather);
}
/**
- * @NoAdminRequired
- *
* Get stored user location
*
- * @return DataResponse which contains coordinates, formatted address and current weather status mode
+ * @return DataResponse<Http::STATUS_OK, WeatherStatusLocationWithMode, array{}>
+ *
+ * 200: Location returned
*/
+ #[NoAdminRequired]
public function getLocation(): DataResponse {
$location = $this->service->getLocation();
return new DataResponse($location);
}
/**
- * @NoAdminRequired
- *
* Get forecast for current location
*
- * @return DataResponse which contains success state and filtered forecast data
+ * @return DataResponse<Http::STATUS_OK, list<WeatherStatusForecast>|array{error: string}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, WeatherStatusSuccess, array{}>
+ *
+ * 200: Forecast returned
+ * 404: Forecast not found
*/
+ #[NoAdminRequired]
public function getForecast(): DataResponse {
$forecast = $this->service->getForecast();
if (isset($forecast['success']) && $forecast['success'] === false) {
@@ -124,24 +109,26 @@ class WeatherStatusController extends OCSController {
}
/**
- * @NoAdminRequired
- *
* Get favorites list
*
- * @return DataResponse which contains the favorite list
+ * @return DataResponse<Http::STATUS_OK, list<string>, array{}>
+ *
+ * 200: Favorites returned
*/
+ #[NoAdminRequired]
public function getFavorites(): DataResponse {
return new DataResponse($this->service->getFavorites());
}
/**
- * @NoAdminRequired
- *
* Set favorites list
*
- * @param array $favorites
- * @return DataResponse success state
+ * @param list<string> $favorites Favorite addresses
+ * @return DataResponse<Http::STATUS_OK, WeatherStatusSuccess, array{}>
+ *
+ * 200: Favorites updated
*/
+ #[NoAdminRequired]
public function setFavorites(array $favorites): DataResponse {
return new DataResponse($this->service->setFavorites($favorites));
}
diff --git a/apps/weather_status/lib/Listeners/BeforeTemplateRenderedListener.php b/apps/weather_status/lib/Listeners/BeforeTemplateRenderedListener.php
new file mode 100644
index 00000000000..5d3b76626b6
--- /dev/null
+++ b/apps/weather_status/lib/Listeners/BeforeTemplateRenderedListener.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\WeatherStatus\Listeners;
+
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Util;
+
+/**
+ * @template-implements IEventListener<BeforeTemplateRenderedEvent>
+ */
+class BeforeTemplateRenderedListener implements IEventListener {
+
+ /**
+ * Inject our status widget script when the dashboard is loaded
+ * We need to do it like this because there is currently no PHP API for registering "status widgets"
+ */
+ public function handle(Event $event): void {
+ if (!($event instanceof BeforeTemplateRenderedEvent)) {
+ return;
+ }
+
+ // Only handle the dashboard
+ if ($event->getResponse()->getApp() !== 'dashboard') {
+ return;
+ }
+
+ Util::addScript('weather_status', 'weather-status');
+ }
+}
diff --git a/apps/weather_status/lib/ResponseDefinitions.php b/apps/weather_status/lib/ResponseDefinitions.php
new file mode 100644
index 00000000000..17d7cebf76e
--- /dev/null
+++ b/apps/weather_status/lib/ResponseDefinitions.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\WeatherStatus;
+
+/**
+ * https://api.met.no/doc/ForecastJSON compact format according to https://docs.api.met.no/doc/locationforecast/datamodel
+ * @psalm-type WeatherStatusForecast = array{
+ * time: string,
+ * data: array{
+ * instant: array{
+ * details: array{
+ * air_pressure_at_sea_level: numeric,
+ * air_temperature: numeric,
+ * cloud_area_fraction: numeric,
+ * relative_humidity: numeric,
+ * wind_from_direction: numeric,
+ * wind_speed: numeric,
+ * },
+ * },
+ * next_12_hours: array{
+ * summary: array{
+ * symbol_code: string,
+ * },
+ * details: array{
+ * precipitation_amount?: numeric,
+ * },
+ * },
+ * next_1_hours: array{
+ * summary: array{
+ * symbol_code: string,
+ * },
+ * details: array{
+ * precipitation_amount?: numeric,
+ * },
+ * },
+ * next_6_hours: array{
+ * summary: array{
+ * symbol_code: string,
+ * },
+ * details: array{
+ * precipitation_amount?: numeric,
+ * },
+ * },
+ * },
+ * }
+ *
+ * @psalm-type WeatherStatusSuccess = array{
+ * success: bool,
+ * }
+ *
+ * @psalm-type WeatherStatusMode = array{
+ * mode: int,
+ * }
+ * @psalm-type WeatherStatusLocation = array{
+ * lat?: string,
+ * lon?: string,
+ * address?: ?string,
+ * }
+ *
+ * @psalm-type WeatherStatusLocationWithSuccess = WeatherStatusLocation&WeatherStatusSuccess
+ *
+ * @psalm-type WeatherStatusLocationWithMode = WeatherStatusLocation&WeatherStatusMode
+ */
+class ResponseDefinitions {
+}
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()];
}
}