Skip to content

Commit

Permalink
Merge pull request #173 from HubSpot/feature/apiRequest
Browse files Browse the repository at this point in the history
apiRequest
  • Loading branch information
ksvirkou-hubspot authored Oct 10, 2022
2 parents 70b022f + 2e13896 commit 2508338
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/Discovery/Discovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace HubSpot\Discovery;

use HubSpot\Http\Request;

/**
* @method Auth\Discovery auth()
* @method Automation\Discovery automation()
Expand All @@ -17,4 +19,22 @@
*/
class Discovery extends DiscoveryBase
{
/**
* @param $options = [
* 'method' => string, // Optional. Default value GET
* 'path' => string, // Optional. Default value null
* 'headers' => array, // Optional.
* 'body' => mixed, // Optional.
* 'authType' => enum(none, accessToken, hapikey), // Optional.
* 'baseUrl' => string, // Optional.
* 'qs' => array, // Optional.
* 'defaultJson' => bool, // Optional.
* ]
*/
public function apiRequest(array $options = [])
{
$request = new Request($this->config, $options);

return $this->client->request($request->getMethod(), $request->getUrl(), $request->getOptionsForSending());
}
}
45 changes: 45 additions & 0 deletions lib/Http/Auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace HubSpot\Http;

use HubSpot\Config;

class Auth
{
public static function chooseAuth(array $options, Config $config): array
{
$auth = [
'type' => null,
'value' => null,
];

if (array_key_exists('authType', $options)) {
if ('none' !== $options['authType'] && array_key_exists($options['authType'], static::getAuthTypes())) {
$method = static::getAuthTypes()[$options['authType']];
if (!empty($config->{$method}())) {
$auth['type'] = $options['authType'];
$auth['value'] = $config->{$method}();
}
}
} else {
foreach (static::getAuthTypes() as $type => $method) {
if (!empty($config->{$method}())) {
$auth['type'] = $type;
$auth['value'] = $config->{$method}();

break;
}
}
}

return $auth;
}

public static function getAuthTypes(): array
{
return [
'accessToken' => 'getAccessToken',
'hapikey' => 'getApiKey',
];
}
}
128 changes: 128 additions & 0 deletions lib/Http/Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace HubSpot\Http;

use HubSpot\Config;

class Request
{
protected array $options = [];
protected string $baseUrl = 'https://api.hubapi.com';
protected $body;
protected Config $config;
protected bool $defaultJson = true;
protected string $url;
protected string $method;
protected array $headers = [];

public function __construct(Config $config, array $options = [])
{
$this->config = $config;
$this->options = $options;
if (!empty($config->getBasePath())) {
$this->baseUrl = $config->getBasePath();
}

if (array_key_exists('defaultJson', $this->options)) {
$this->defaultJson = $this->options['defaultJson'];
}
$this->method = $this->options['method'] ?? 'GET';

$this->initHeaders();
$this->applyAuth();

$this->url = $this->generateUrl();
$this->setBody();
}

public function getUrl(): string
{
return $this->url;
}

public function getMethod(): string
{
return $this->method;
}

public function getOptionsForSending(): array
{
$options = [];
if (!empty($this->headers)) {
$options['headers'] = $this->headers;
}

if (!empty($this->body)) {
$options['body'] = $this->body;
}

return $options;
}

protected function applyAuth()
{
$auth = Auth::chooseAuth($this->options, $this->config);

if ($auth['type']) {
if ('hapikey' === $auth['type']) {
$this->options['qs']['hapikey'] = $auth['value'];
}

if ('accessToken' === $auth['type']) {
$this->headers['Authorization'] = "Bearer {$auth['value']}";
}
}
}

protected function initHeaders()
{
if ($this->defaultJson) {
$this->headers = [
'Content-Type' => 'application/json',
];
}

$this->headers = array_merge($this->headers, $this->getDefaultHeaders());
if (array_key_exists('headers', $this->options)) {
$this->headers = array_merge($this->headers, $this->options['headers']);
}
}

protected function getDefaultHeaders(): array
{
$headers = [
'User-agent' => $this->config->getUserAgent(),
];

if ($this->defaultJson) {
$headers['Accept'] = 'application/json, */*;q=0.8';
}

return $headers;
}

protected function generateUrl(): string
{
$urlStr = $this->baseUrl;
if (array_key_exists('baseUrl', $this->options)) {
$urlStr = $this->options['baseUrl'];
}
$urlStr .= $this->options['path'] ?? '';

if (array_key_exists('qs', $this->options) && !empty($this->options['qs'])) {
$urlStr .= '?'.http_build_query($this->options['qs'], '', '&', PHP_QUERY_RFC3986);
}

return $urlStr;
}

protected function setBody()
{
if (array_key_exists('body', $this->options)) {
$this->body = $this->options['body'];
if ($this->defaultJson) {
$this->body = json_encode($this->body);
}
}
}
}
109 changes: 109 additions & 0 deletions tests/Unit/Http/RequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace Hubspot\Tests\Unit\Utils;

use HubSpot\Config;
use HubSpot\Http\Request;
use PHPUnit\Framework\TestCase;

/**
* @internal
* @coversNothing
*/
class RequestTest extends TestCase
{
public const BASE_URL = 'https://api.hubapi.com';

/** @test */
public function emptyConfigAndOptions(): void
{
$config = new Config();

$request = new Request($config, []);

$this->assertSame($this::BASE_URL, $request->getUrl());
$this->assertSame('GET', $request->getMethod());
$this->assertSame(['headers' => $this->getHeaders($config)], $request->getOptionsForSending());
}

/** @test */
public function getContacts(): void
{
$config = new Config();
$config->setApiKey('api-key');

$request = new Request($config, [
'path' => '/crm/v3/objects/contacts',
]);

$this->assertSame($this::BASE_URL.'/crm/v3/objects/contacts?hapikey=api-key', $request->getUrl());
$this->assertSame('GET', $request->getMethod());
$this->assertSame(['headers' => $this->getHeaders($config)], $request->getOptionsForSending());
}

/** @test */
public function createContacts(): void
{
$config = new Config();

$body = [
'properties' => [
'email' => '[email protected]',
],
];

$request = new Request($config, [
'path' => '/crm/v3/objects/contacts',
'method' => 'POST',
'body' => $body,
]);

$this->assertSame($this::BASE_URL.'/crm/v3/objects/contacts', $request->getUrl());
$this->assertSame('POST', $request->getMethod());
$this->assertSame([
'headers' => $this->getHeaders($config),
'body' => json_encode($body),
], $request->getOptionsForSending());
}

/** @test */
public function createContactsDefaultJsonFasle(): void
{
$config = new Config();

$body = [
'properties' => [
'email' => '[email protected]',
],
];

$request = new Request($config, [
'path' => '/crm/v3/objects/contacts',
'method' => 'POST',
'body' => $body,
'defaultJson' => false,
]);

$this->assertSame($this::BASE_URL.'/crm/v3/objects/contacts', $request->getUrl());
$this->assertSame('POST', $request->getMethod());
$this->assertSame([
'headers' => $this->getHeaders($config, false),
'body' => $body,
], $request->getOptionsForSending());
}

protected function getHeaders(Config $config, bool $defaultJson = true): array
{
$headers = [
'Content-Type' => 'application/json',
'User-agent' => $config->getUserAgent(),
'Accept' => 'application/json, */*;q=0.8',
];

if (!$defaultJson) {
unset($headers['Accept'], $headers['Content-Type']);
}

return $headers;
}
}

0 comments on commit 2508338

Please sign in to comment.