Skip to content

Commit

Permalink
Merge pull request #14 from nspalo/development
Browse files Browse the repository at this point in the history
BWA-Dev-4-Weather-App-API-Refactor
  • Loading branch information
nspalo authored Sep 8, 2023
2 parents 1223e99 + d99af59 commit 371fc47
Showing 23 changed files with 551 additions and 102 deletions.
25 changes: 25 additions & 0 deletions src/app/Exceptions/BaseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\Exceptions;

use Exception;
use Throwable;

class BaseException extends Exception
{
private ?array $errors;

public function __construct($message = '', $code = 0, ?Throwable $previous = null, ?array $errors = null)
{
parent::__construct($message, $code, $previous);

$this->errors = $errors;
}

public function getErrors(): ?array
{
return $this->errors;
}
}
Original file line number Diff line number Diff line change
@@ -4,23 +4,24 @@

namespace App\Http\Controllers\API\WeatherApp;

use App\Enums\WeatherTypeEnum;
use App\Http\Controllers\Controller;
use App\Services\GeoapifyApi\Interfaces\GeoapifyApiServiceInterface;
use App\Services\OpenWeatherApi\Interfaces\OpenWeatherApiServiceInterface;
use App\Services\OpenWeatherApi\Interfaces\OpenWeatherApiServiceFactoryInterface;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class WeatherUpdateApiController extends Controller
{
protected GeoapifyApiServiceInterface $geoapifyGeocodingService;
protected OpenWeatherApiServiceInterface $weatherApiService;
protected OpenWeatherApiServiceFactoryInterface $weatherApiServiceFactory;

public function __construct(
GeoapifyApiServiceInterface $geoapifyGeocodingService,
OpenWeatherApiServiceInterface $weatherApiService
OpenWeatherApiServiceFactoryInterface $weatherApiServiceFactory
) {
$this->geoapifyGeocodingService = $geoapifyGeocodingService;
$this->weatherApiService = $weatherApiService;
$this->weatherApiServiceFactory = $weatherApiServiceFactory;
}

public function __invoke(Request $request): JsonResource
@@ -29,15 +30,20 @@ public function __invoke(Request $request): JsonResource

$responseGeolocation = $this->geoapifyGeocodingService->getGeolocation($location);

$responseCurrentWeather = $this->weatherApiService->getWeatherUpdate($responseGeolocation['lon'], $responseGeolocation['lat']);
$responseForecastWeather = $this->weatherApiService->getWeatherForecast($responseGeolocation['lon'], $responseGeolocation['lat']);
$responseCurrentWeather = $this->weatherApiServiceFactory->make(WeatherTypeEnum::Current)
->getWeatherData($responseGeolocation);

return new JsonResource([
$responseForecastWeather = $this->weatherApiServiceFactory->make(WeatherTypeEnum::Forecast)
->getWeatherData($responseGeolocation);

$data = [
'geolocation' => $responseGeolocation,
'weather' => [
'geolocation' => $responseGeolocation,
'current' => $responseCurrentWeather->json(),
'forecast' => $responseForecastWeather->json(),
],
]);
'current' => $responseCurrentWeather->getResponse(),
'forecast' => $responseForecastWeather->getResponse(),
]
];

return new JsonResource($data);
}
}
37 changes: 35 additions & 2 deletions src/app/Http/Controllers/WeatherApp/WeatherUpdateController.php
Original file line number Diff line number Diff line change
@@ -4,13 +4,46 @@

namespace App\Http\Controllers\WeatherApp;

use App\Enums\WeatherTypeEnum;
use App\Http\Controllers\Controller;
use App\Services\GeoapifyApi\Interfaces\GeoapifyApiServiceInterface;
use App\Services\OpenWeatherApi\Interfaces\OpenWeatherApiServiceFactoryInterface;
use Illuminate\Http\Request;
use Illuminate\View\View;

class WeatherUpdateController extends Controller
{
public function index(): View
protected GeoapifyApiServiceInterface $geoapifyGeocodingService;
protected OpenWeatherApiServiceFactoryInterface $weatherApiServiceFactory;

public function __construct(
GeoapifyApiServiceInterface $geoapifyGeocodingService,
OpenWeatherApiServiceFactoryInterface $weatherApiServiceFactory
) {
$this->geoapifyGeocodingService = $geoapifyGeocodingService;
$this->weatherApiServiceFactory = $weatherApiServiceFactory;
}

public function index(Request $request): View
{
return view('weather-app/weather-update');
$location = $request->get('location') ?? \config('services.api.geoapify.default_search');

$responseGeolocation = $this->geoapifyGeocodingService->getGeolocation($location);

$responseCurrentWeather = $this->weatherApiServiceFactory->make(WeatherTypeEnum::Current)
->getWeatherData($responseGeolocation);

$responseForecastWeather = $this->weatherApiServiceFactory->make(WeatherTypeEnum::Forecast)
->getWeatherData($responseGeolocation);

$data = [
'geolocation' => $responseGeolocation,
'weather' => [
'current' => $responseCurrentWeather->getResponse(),
'forecast' => $responseForecastWeather->getResponse(),
]
];

return view('weather-app/weather-update', $data);
}
}
27 changes: 27 additions & 0 deletions src/app/Http/Resources/Resource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

abstract class Resource extends JsonResource
{
/**
* Return this resource as an array
*
* @noinspection PhpMissingParentCallCommonInspection
*
* @param Request $request
*
* @return string[]
*/
public function toArray($request): array
{
return $this->getResponse();
}

abstract public function getResponse(): array;
}
20 changes: 19 additions & 1 deletion src/app/Providers/WeatherAppServiceProvider.php
Original file line number Diff line number Diff line change
@@ -2,12 +2,18 @@

namespace App\Providers;

use App\Services\ConfigurationMapper\Interfaces\ServiceConfigurationMapperInterface;
use App\Services\ConfigurationMapper\ServiceConfigurationMapper;
use App\Services\GeoapifyApi\GeocodingService;
use App\Services\GeoapifyApi\Interfaces\GeoapifyApiServiceInterface;
use App\Services\OpenWeatherApi\Interfaces\OpenWeatherApiServiceFactoryInterface;
use App\Services\OpenWeatherApi\Interfaces\OpenWeatherApiServiceInterface;
use App\Services\OpenWeatherApi\OpenWeatherApiServiceFactory;
use App\Services\OpenWeatherApi\WeatherForecastService;
use App\Services\OpenWeatherApi\WeatherUpdateService;
use App\Services\UrlQueryStringBuilder\Interfaces\UrlQueryStringBuilderServiceInterface;
use App\Services\UrlQueryStringBuilder\UrlQueryStringBuilderService;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\ServiceProvider;

class WeatherAppServiceProvider extends ServiceProvider
@@ -29,8 +35,20 @@ public function boot(): void
*/
public function register(): void
{
$this->app->bind(ServiceConfigurationMapperInterface::class, ServiceConfigurationMapper::class);
$this->app->bind(UrlQueryStringBuilderServiceInterface::class, UrlQueryStringBuilderService::class);
$this->app->bind(GeoapifyApiServiceInterface::class, GeocodingService::class);
$this->app->bind(OpenWeatherApiServiceInterface::class, WeatherUpdateService::class);

$this->app->singleton(
OpenWeatherApiServiceFactoryInterface::class,
static function (Application $app): OpenWeatherApiServiceFactory {
$app->tag([
WeatherUpdateService::class,
WeatherForecastService::class,
], [OpenWeatherApiServiceInterface::class]);

return new OpenWeatherApiServiceFactory($app->tagged(OpenWeatherApiServiceInterface::class));
}
);
}
}
17 changes: 17 additions & 0 deletions src/app/Services/Collector/ServiceCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace App\Services\Collector;

class ServiceCollector
{
public static function filterByClass(iterable $objects, string $class): array
{
$objects = $objects instanceof \Traversable ? \iterator_to_array($objects) : (array) $objects;

return \array_filter($objects, static function ($object) use ($class): bool {
return $object instanceof $class;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace App\Services\ConfigurationMapper\Exceptions;

use App\Exceptions\BaseException;

class UnknownServiceConfigurationException extends BaseException
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace App\Services\ConfigurationMapper\Interfaces;

interface ServiceConfigurationMapperInterface
{
public function loadConfig(?string $config = null): void;
public function map(array $keyMapping): array;
public function getByKey(string $key): ?string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace App\Services\ConfigurationMapper;

use App\Services\ConfigurationMapper\Exceptions\UnknownServiceConfigurationException;
use App\Services\ConfigurationMapper\Interfaces\ServiceConfigurationMapperInterface;

class ServiceConfigurationMapper implements ServiceConfigurationMapperInterface
{
private ?array $config;

public function __construct()
{
$this->config = null;
}

/**
* @throws UnknownServiceConfigurationException
*/
public function loadConfig(?string $config = null): void
{
if ($config === null) {
throw new UnknownServiceConfigurationException();
}

$this->config = \config($config);
}

/**
* @throws UnknownServiceConfigurationException
*/
public function map(array $keyMapping): array
{
if ($this->config === null) {
throw new UnknownServiceConfigurationException();
}

$resolved = [];
foreach ($this->config as $key => $value) {
$foundKey = array_search($key, $keyMapping, true);

if($foundKey !== false) {
$resolved[$foundKey] = $value;
}
}

return $resolved;
}

/**
* @throws UnknownServiceConfigurationException
*/
public function getByKey(string $key): ?string
{
if ($this->config === null) {
throw new UnknownServiceConfigurationException();
}

$value = array_search($key, array_flip($this->config), true);

if ($value === false) {
return null;
}

return $value;
}
}
Loading

0 comments on commit 371fc47

Please sign in to comment.