Skip to content

Commit

Permalink
Release 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
fern-api[bot] committed Nov 18, 2024
0 parents commit 45f9049
Show file tree
Hide file tree
Showing 84 changed files with 5,248 additions and 0 deletions.
1 change: 1 addition & 0 deletions .fernignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Specify files that shouldn't be modified by Fern
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: ci

on: [push]

jobs:
compile:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"

- name: Install tools
run: |
composer install
- name: Build
run: |
composer build
- name: Analyze
run: |
composer analyze
unit-tests:
runs-on: ubuntu-latest

steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"

- name: Install tools
run: |
composer install
- name: Run Tests
run: |
composer test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.php-cs-fixer.cache
.phpunit.result.cache
composer.lock
vendor/
40 changes: 40 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

{
"name": "ssoready/ssoready",
"version": "0.1.0",
"description": "Ssoready PHP Library",
"keywords": [
"ssoready",
"api",
"sdk"
],
"license": [],
"require": {
"php": "^8.1",
"ext-json": "*",
"guzzlehttp/guzzle": "^7.9"
},
"require-dev": {
"phpunit/phpunit": "^9.0",
"friendsofphp/php-cs-fixer": "3.5.0",
"phpstan/phpstan": "^1.12"
},
"autoload": {
"psr-4": {
"Ssoready\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"\\Ssoready\\Tests\\": "tests/"
}
},
"scripts": {
"build": [
"@php -l src",
"@php -l tests"
],
"test": "phpunit",
"analyze": "phpstan analyze src tests"
}
}
5 changes: 5 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
parameters:
level: max
paths:
- src
- tests
7 changes: 7 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<phpunit bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="Test Suite">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
</phpunit>
22 changes: 22 additions & 0 deletions src/Core/Client/BaseApiRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Ssoready\Core\Client;

abstract class BaseApiRequest
{
/**
* @param string $baseUrl The base URL for the request
* @param string $path The path for the request
* @param HttpMethod $method The HTTP method for the request
* @param array<string, string> $headers Additional headers for the request (optional)
* @param array<string, mixed> $query Query parameters for the request (optional)
*/
public function __construct(
public readonly string $baseUrl,
public readonly string $path,
public readonly HttpMethod $method,
public readonly array $headers = [],
public readonly array $query = [],
) {
}
}
12 changes: 12 additions & 0 deletions src/Core/Client/HttpMethod.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Ssoready\Core\Client;

enum HttpMethod
{
case GET;
case POST;
case PUT;
case PATCH;
case DELETE;
}
146 changes: 146 additions & 0 deletions src/Core/Client/RawClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

namespace Ssoready\Core\Client;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Utils;
use InvalidArgumentException;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Ssoready\Core\Json\JsonApiRequest;
use Ssoready\Core\Multipart\MultipartApiRequest;

class RawClient
{
/**
* @var ClientInterface $client
*/
private ClientInterface $client;

/**
* @var array<string, string> $headers
*/
private array $headers;

/**
* @param ?array{
* baseUrl?: string,
* client?: ClientInterface,
* headers?: array<string, string>,
* } $options
*/
public function __construct(
public readonly ?array $options = null,
) {
$this->client = $this->options['client'] ?? new Client();
$this->headers = $this->options['headers'] ?? [];
}

/**
* @throws ClientExceptionInterface
*/
public function sendRequest(
BaseApiRequest $request,
): ResponseInterface {
$httpRequest = $this->buildRequest($request);
return $this->client->send($httpRequest);
}

private function buildRequest(
BaseApiRequest $request
): Request {
$url = $this->buildUrl($request);
$headers = $this->encodeHeaders($request);
$body = $this->encodeRequestBody($request);
return new Request(
$request->method->name,
$url,
$headers,
$body,
);
}

/**
* @return array<string, string>
*/
private function encodeHeaders(
BaseApiRequest $request
): array {
return match (get_class($request)) {
JsonApiRequest::class => array_merge(
["Content-Type" => "application/json"],
$this->headers,
$request->headers
),
MultipartApiRequest::class => array_merge(
$this->headers,
$request->headers
),
default => throw new InvalidArgumentException('Unsupported request type: ' . get_class($request)),
};
}

private function encodeRequestBody(
BaseApiRequest $request
): ?StreamInterface {
return match (get_class($request)) {
JsonApiRequest::class => $request->body != null ? Utils::streamFor(json_encode($request->body)) : null,
MultipartApiRequest::class => $request->body != null ? new MultipartStream($request->body->toArray()) : null,
default => throw new InvalidArgumentException('Unsupported request type: '.get_class($request)),
};
}

private function buildUrl(
BaseApiRequest $request
): string {
$baseUrl = $request->baseUrl;
$trimmedBaseUrl = rtrim($baseUrl, '/');
$trimmedBasePath = ltrim($request->path, '/');
$url = "{$trimmedBaseUrl}/{$trimmedBasePath}";

if (!empty($request->query)) {
$url .= '?' . $this->encodeQuery($request->query);
}

return $url;
}

/**
* @param array<string, mixed> $query
*/
private function encodeQuery(
array $query
): string {
$parts = [];
foreach ($query as $key => $value) {
if (is_array($value)) {
foreach ($value as $item) {
$parts[] = urlencode($key).'='.$this->encodeQueryValue($item);
}
} else {
$parts[] = urlencode($key).'='.$this->encodeQueryValue($value);
}
}
return implode('&', $parts);
}

private function encodeQueryValue(
mixed $value
): string {
if (is_string($value)) {
return urlencode($value);
}
if (is_scalar($value)) {
return urlencode((string)$value);
}
if (is_null($value)) {
return 'null';
}
// Unreachable, but included for a best effort.
return urlencode(strval(json_encode($value)));
}
}
28 changes: 28 additions & 0 deletions src/Core/Json/JsonApiRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Ssoready\Core\Json;

use Ssoready\Core\Client\BaseApiRequest;
use Ssoready\Core\Client\HttpMethod;

class JsonApiRequest extends BaseApiRequest
{
/**
* @param string $baseUrl The base URL for the request
* @param string $path The path for the request
* @param HttpMethod $method The HTTP method for the request
* @param array<string, string> $headers Additional headers for the request (optional)
* @param array<string, mixed> $query Query parameters for the request (optional)
* @param mixed|null $body The JSON request body (optional)
*/
public function __construct(
string $baseUrl,
string $path,
HttpMethod $method,
array $headers = [],
array $query = [],
public readonly mixed $body = null
) {
parent::__construct($baseUrl, $path, $method, $headers, $query);
}
}
Loading

0 comments on commit 45f9049

Please sign in to comment.