kdabek/http-client

View on GitHub
src/Client.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

declare(strict_types=1);

namespace Kdabek\HttpClient;

use Kdabek\HttpClient\Auth\Credentials\CredentialsInterface;
use Kdabek\HttpClient\Auth\Credentials\LoginAndPassword;
use Kdabek\HttpClient\Auth\Credentials\Token;
use Kdabek\HttpClient\Auth\Factory\AuthorizationFactoryInterface;
use Kdabek\HttpClient\Header\Header;
use Kdabek\HttpClient\Header\MimeType;
use Kdabek\HttpClient\Response\Response;
use Kdabek\HttpClient\Response\ResponseInterface;
use Kdabek\HttpClient\Transport\TransportInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Log\LoggerInterface;

class Client
{
    private const DEFAULT_HEADERS = [
        Header::ACCEPT       => MimeType::JSON,
        Header::CONTENT_TYPE => MimeType::JSON
    ];
    private RequestFactoryInterface $requestFactory;
    private TransportInterface $transport;
    private AuthorizationFactoryInterface $authorizationFactory;
    private Header $headers;
    private ?LoggerInterface $logger = null;

    public function __construct(
        RequestFactoryInterface $requestFactory,
        TransportInterface $transport,
        AuthorizationFactoryInterface $authorizationFactory
    ) {
        $this->requestFactory = $requestFactory;
        $this->transport = $transport;
        $this->authorizationFactory = $authorizationFactory;
        $this->headers = new Header(self::DEFAULT_HEADERS);
    }

    public function get(string $url): ResponseInterface
    {
        return $this->request('GET', $url);
    }

    public function post(string $url, array $data = []): ResponseInterface
    {
        return $this->request('POST', $url, $data);
    }

    public function put(string $url, array $data = []): ResponseInterface
    {
        return $this->request('PUT', $url, $data);
    }

    public function delete(string $url, array $data = []): ResponseInterface
    {
        return $this->request('DELETE', $url, $data);
    }

    public function withHeaders(array $headers): self
    {
        $this->headers->exchangeArray(array_merge($this->headers->getArrayCopy(), $headers));

        return $this;
    }

    public function clearHeaders(): self
    {
        $this->headers->exchangeArray(self::DEFAULT_HEADERS);

        return $this;
    }

    public function withBasicAuth(string $login, string $password): self
    {
        $this->setAuth(new LoginAndPassword($login, $password));

        return $this;
    }

    public function withToken(string $token): self
    {
        $this->setAuth(new Token($token));

        return $this;
    }

    public function clearAuth(): self
    {
        $this->headers->offsetUnset(Header::AUTHORIZATION);

        return $this;
    }

    public function setLogger(LoggerInterface $logger): self
    {
        $this->logger = $logger;

        return $this;
    }

    private function setAuth(CredentialsInterface $credentials): void
    {
        $strategy = $this->authorizationFactory->createFrom($credentials);
        $this->withHeaders($strategy->getCredentials());
    }

    protected function request(string $method, string $url, array $data = []): ResponseInterface
    {
        $request = $this->headers->bindTo(
            $this->requestFactory->createRequest($method, $url)
        );
        $request->getBody()->write(json_encode($data));
        $this->logger?->debug('REQUEST', ['payload' => $request]);
        $response = $this->transport->request($request);
        $this->logger?->debug('RESPONSE', ['payload' => $response]);

        return new Response($response);
    }
}