Skip to content

Commit c53f047

Browse files
committed
WIP Client
1 parent 55cdb90 commit c53f047

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+3027
-0
lines changed

examples/conditions-async.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
use ApiClients\Client\WeatherUnderground\AsyncClient;
4+
use ApiClients\Client\WeatherUnderground\Resource\ConditionInterface;
5+
use React\EventLoop\Factory;
6+
use function ApiClients\Foundation\resource_pretty_print;
7+
8+
require dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor/autoload.php';
9+
10+
$loop = Factory::create();
11+
$client = AsyncClient::create($loop, require 'resolve_token.php');
12+
13+
$client->conditions('Broek_op_Langedijk')->done(function (ConditionInterface $user) {
14+
resource_pretty_print($user);
15+
});
16+
17+
$loop->run();

examples/resolve_token.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
$keyFile = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'token.php';
4+
5+
if (!file_exists($keyFile)) {
6+
echo 'No key file find, copy token.sample.php to token.php and add a token from https://github.com/settings/tokens to run examples.', PHP_EOL;
7+
exit(1);
8+
}
9+
10+
return require $keyFile;

src/ApiSettings.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground;
4+
5+
use ApiClients\Foundation\Hydrator\Options as HydratorOptions;
6+
use ApiClients\Foundation\Options as FoundationOptions;
7+
use ApiClients\Foundation\Transport\Middleware\JsonDecodeMiddleware;
8+
use ApiClients\Foundation\Transport\Middleware\JsonEncodeMiddleware;
9+
use ApiClients\Foundation\Transport\Options as TransportOptions;
10+
use ApiClients\Foundation\Transport\UserAgentStrategies;
11+
use function ApiClients\Foundation\options_merge;
12+
13+
final class ApiSettings
14+
{
15+
const NAMESPACE = 'ApiClients\\Client\\WeatherUnderground\\Resource';
16+
17+
const TRANSPORT_OPTIONS = [
18+
FoundationOptions::HYDRATOR_OPTIONS => [
19+
HydratorOptions::NAMESPACE => self::NAMESPACE,
20+
HydratorOptions::NAMESPACE_DIR => __DIR__ . DIRECTORY_SEPARATOR . 'Resource' . DIRECTORY_SEPARATOR,
21+
],
22+
FoundationOptions::TRANSPORT_OPTIONS => [
23+
TransportOptions::HOST => 'api.wunderground.com',
24+
TransportOptions::MIDDLEWARE => [
25+
JsonDecodeMiddleware::class,
26+
JsonEncodeMiddleware::class,
27+
],
28+
TransportOptions::USER_AGENT_STRATEGY => UserAgentStrategies::PACKAGE_VERSION,
29+
TransportOptions::PACKAGE => 'api-clients/weather-underground',
30+
],
31+
];
32+
33+
public static function getOptions(
34+
string $token,
35+
array $suppliedOptions,
36+
string $suffix
37+
): array {
38+
$options = options_merge(self::TRANSPORT_OPTIONS, $suppliedOptions);
39+
$options[FoundationOptions::TRANSPORT_OPTIONS][TransportOptions::PATH] = '/api/' . $token . '/';
40+
$options[FoundationOptions::HYDRATOR_OPTIONS][HydratorOptions::NAMESPACE_SUFFIX] = $suffix;
41+
return $options;
42+
}
43+
}

src/AsyncClient.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground;
4+
5+
use ApiClients\Client\WeatherUnderground\CommandBus\Command;
6+
use ApiClients\Foundation\ClientInterface;
7+
use ApiClients\Foundation\Factory;
8+
use React\EventLoop\LoopInterface;
9+
use React\Promise\PromiseInterface;
10+
use Rx\Observable;
11+
use function ApiClients\Tools\Rx\unwrapObservableFromPromise;
12+
use function React\Promise\resolve;
13+
14+
final class AsyncClient
15+
{
16+
/**
17+
* @var ClientInterface
18+
*/
19+
private $client;
20+
21+
/**
22+
* @param LoopInterface $loop
23+
* @param string $token
24+
* @param array $options
25+
* @return AsyncClient
26+
*/
27+
public static function create(
28+
LoopInterface $loop,
29+
string $token,
30+
array $options = []
31+
): self {
32+
$options = ApiSettings::getOptions($token, $options, 'Async');
33+
$client = Factory::create($loop, $options);
34+
return new self($client);
35+
}
36+
37+
/**
38+
* @param ClientInterface $client
39+
*/
40+
private function __construct(ClientInterface $client)
41+
{
42+
$this->client = $client;
43+
}
44+
45+
public function conditions(string $location): PromiseInterface
46+
{
47+
return $this->client->handle(new Command\ConditionsCommand($location));
48+
}
49+
}

src/AuthenticationInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground;
4+
5+
interface AuthenticationInterface
6+
{
7+
public function getOptions(): array;
8+
}

src/Client.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground;
4+
5+
use ApiClients\Client\WeatherUnderground\Resource\UserInterface;
6+
use React\EventLoop\Factory;
7+
use React\EventLoop\LoopInterface;
8+
use function Clue\React\Block\await;
9+
10+
final class Client
11+
{
12+
/**
13+
* @var LoopInterface
14+
*/
15+
private $loop;
16+
17+
/**
18+
* @var AsyncClient
19+
*/
20+
private $client;
21+
22+
public function __construct(AuthenticationInterface $auth)
23+
{
24+
$this->loop = Factory::create();
25+
$this->client = AsyncClient::create($this->loop, $auth);
26+
}
27+
28+
public function user(string $user): UserInterface
29+
{
30+
return await(
31+
$this->client->user($user),
32+
$this->loop
33+
);
34+
}
35+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground\CommandBus\Command;
4+
5+
use WyriHaximus\Tactician\CommandHandler\Annotations\Handler;
6+
7+
/**
8+
* @Handler("ApiClients\Client\WeatherUnderground\CommandBus\Handler\ConditionsHandler")
9+
*/
10+
final class ConditionsCommand
11+
{
12+
/**
13+
* @var string
14+
*/
15+
private $location;
16+
17+
/**
18+
* @param string $location
19+
*/
20+
public function __construct(string $location = '')
21+
{
22+
$this->location = $location;
23+
}
24+
25+
/**
26+
* @return string
27+
*/
28+
public function getLocation(): string
29+
{
30+
return $this->location;
31+
}
32+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground\CommandBus\Handler;
4+
5+
use ApiClients\Client\WeatherUnderground\CommandBus\Command\ConditionsCommand;
6+
use ApiClients\Client\WeatherUnderground\Resource\ConditionInterface;
7+
use ApiClients\Tools\Services\Client\FetchAndHydrateService;
8+
use React\Promise\PromiseInterface;
9+
use function React\Promise\resolve;
10+
use function WyriHaximus\React\futureFunctionPromise;
11+
12+
final class ConditionsHandler
13+
{
14+
/**
15+
* @var FetchAndHydrateService
16+
*/
17+
private $service;
18+
19+
/**
20+
* @param FetchAndHydrateService $service
21+
*/
22+
public function __construct(FetchAndHydrateService $service)
23+
{
24+
$this->service = $service;
25+
}
26+
27+
/**
28+
* Fetch the given repository and hydrate it
29+
*
30+
* @param ConditionsCommand $command
31+
* @return PromiseInterface
32+
*/
33+
public function handle(ConditionsCommand $command): PromiseInterface
34+
{
35+
return $this->service->handle(
36+
'conditions/q/' . $command->getLocation() . '.json',
37+
'current_observation',
38+
ConditionInterface::HYDRATE_CLASS
39+
);
40+
}
41+
}

src/Resource/Async/Condition.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground\Resource\Async;
4+
5+
use ApiClients\Client\WeatherUnderground\Resource\Condition as BaseCondition;
6+
7+
class Condition extends BaseCondition
8+
{
9+
public function refresh() : Condition
10+
{
11+
throw new \Exception('TODO: create refresh method!');
12+
}
13+
}

src/Resource/Async/EmptyCondition.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Client\WeatherUnderground\Resource\Async;
4+
5+
use ApiClients\Client\WeatherUnderground\Resource\EmptyCondition as BaseEmptyCondition;
6+
7+
class EmptyCondition extends BaseEmptyCondition
8+
{
9+
}

0 commit comments

Comments
 (0)