diff --git a/docker/containers/php/Dockerfile b/docker/containers/php/Dockerfile index 02748e6..7e2a6a0 100644 --- a/docker/containers/php/Dockerfile +++ b/docker/containers/php/Dockerfile @@ -5,4 +5,4 @@ FROM php:8.1-fpm-alpine RUN apk --no-cache add zip libzip-dev \ && docker-php-ext-configure zip \ && docker-php-ext-install zip mysqli pdo pdo_mysql \ - && docker-php-ext-enable pdo_mysql \ + && docker-php-ext-enable pdo_mysql diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index b05bc2a..f1d9721 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -55,6 +55,8 @@ services: volumes: - "${PATH_CONFIG_PHP}:/usr/local/etc/php/php.ini" - "${PATH_PROJECT_SOURCE}:/var/www/html" + links: + - php depends_on: - php entrypoint: ['composer'] diff --git a/src/app/Enums/WeatherTypeEnum.php b/src/app/Enums/WeatherTypeEnum.php new file mode 100644 index 0000000..8dd8774 --- /dev/null +++ b/src/app/Enums/WeatherTypeEnum.php @@ -0,0 +1,11 @@ +weatherApiKey = \config('services.api.open_weather.key'); + $this->weatherApiUnit = \config('services.api.open_weather.unit'); + $this->weatherApiOutput = \config('services.api.open_weather.max_output'); + $this->weatherApiUri = \config('services.api.open_weather.uri'); + $this->geoapifyApiKey = \config('services.api.geoapify.key'); + $this->geoapifyApiUri = \config('services.api.geoapify.uri'); + $this->geoapifyApiFilter = \config('services.api.geoapify.filter'); + $this->geoapifyApiFormat = \config('services.api.geoapify.format'); + $this->geoapifyApiLang = \config('services.api.geoapify.lang'); + $this->geoapifyApiMaxOutput = \config('services.api.geoapify.max_output'); + $this->geoapifyApiType = \config('services.api.geoapify.type'); + } + + public function __invoke(Request $request): JsonResource + { + $location = $request->get('location') ?? 'Metro Manila, Philippines'; + + $responseGeolocation = $this->getGeoapifyGeolocation($location); + + $responseCurrentWeather = $this->getWeatherUpdate($responseGeolocation['lon'], $responseGeolocation['lat']); + $responseForecastWeather = $this->getWeatherForecast($responseGeolocation['lon'], $responseGeolocation['lat']); + + return new JsonResource([ + 'weather' => [ + 'geolocation' => $responseGeolocation, + 'current' => $responseCurrentWeather->json(), + 'forecast' => $responseForecastWeather->json(), + ], + ]); + } + + private function buildQueryString(array $queryParam): string + { + return implode( + '&', + array_map( + static function($key, $value){ + return $key . '=' . $value; + }, + array_keys($queryParam), + $queryParam + ) + ); + } + + private function buildGeoapifyApiUrl(string $location): string + { + $queryParam = [ + 'text' => $location, + 'type' => $this->geoapifyApiType, + 'limit' => $this->geoapifyApiMaxOutput, + 'lang' => $this->geoapifyApiLang, + 'filter' => $this->geoapifyApiFilter, + 'format' => $this->geoapifyApiFormat, + 'apiKey' => $this->geoapifyApiKey, + ]; + + $queryString = $this->buildQueryString($queryParam); + + return 'https://' . $this->geoapifyApiUri . '?' . $queryString; + } + + private function getGeoapifyGeolocation(string $location): array + { + $geolocationUrl = $this->buildGeoapifyApiUrl($location); + $responseGeolocation = Http::get($geolocationUrl); + $data = $responseGeolocation->json('results'); + + return [ + 'lon' => $data[0]['lon'], + 'lat' => $data[0]['lat'], + ]; + } + + private function buildWeatherApiUrl(WeatherTypeEnum $requestType, float $lon, float $lat): string + { + $queryParam = [ + 'lon' => $lon, + 'lat' => $lat, + 'units' => $this->weatherApiUnit, + 'appid' => $this->weatherApiKey, + ]; + + if ($requestType === WeatherTypeEnum::Forecast) { + $queryParam['cnt'] = $this->weatherApiOutput; + } + + $queryString = $this->buildQueryString($queryParam); + + return 'https://' . $this->weatherApiUri . '/' . $requestType->value . '?' . $queryString; + } + + private function getWeatherUpdate(float $lon, float $lat): Response + { + $currentWeatherUrl = $this->buildWeatherApiUrl(WeatherTypeEnum::Current, $lon, $lat); + + return Http::get($currentWeatherUrl); + } + + private function getWeatherForecast(float $lon, float $lat): Response + { + $forecastWeatherUrl = $this->buildWeatherApiUrl(WeatherTypeEnum::Forecast, $lon, $lat); + + return Http::get($forecastWeatherUrl); + } +} diff --git a/src/config/services.php b/src/config/services.php index 0ace530..b2a216f 100644 --- a/src/config/services.php +++ b/src/config/services.php @@ -31,4 +31,21 @@ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), ], + 'api' => [ + 'open_weather' => [ + 'key' => env('OPEN_WEATHER_API_KEY', ''), + 'max_output' => env('OPEN_WEATHER_MAX_OUTPUT', '5'), + 'unit' => env('OPEN_WEATHER_UNIT', 'metric'), + 'uri' => env('OPEN_WEATHER_API_URI', ''), + ], + 'geoapify' => [ + 'filter' => env('GEOAPIFY_FILTER', 'countrycode:none'), + 'format' => env('GEOAPIFY_FORMAT', 'json'), + 'key' => env('GEOAPIFY_API_KEY', ''), + 'lang' => env('GEOAPIFY_LANG', 'en'), + 'max_output' => env('GEOAPIFY_MAX_OUTPUT', '1'), + 'type' => env('GEOAPIFY_TYPE', 'city'), + 'uri' => env('GEOAPIFY_API_URI', ''), + ], + ], ]; diff --git a/src/routes/api.php b/src/routes/api.php index eb6fa48..9f13e07 100644 --- a/src/routes/api.php +++ b/src/routes/api.php @@ -1,5 +1,6 @@ get('/user', function (Request $request) { return $request->user(); }); + +// Bizmates Ph Weather App API Routes +Route::get('/weather-update', [ + 'as' => 'forecast', + 'uses' => WeatherUpdateController::class, +]);