Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/Analytics/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function call(string $method, string $path = '', array $headers = [], arr
$responseType = '';
$responseBody = '';

switch ($headers['Content-Type']) {
switch ($headers['Content-Type'] ?? '') {
Comment thread
PineappleIOnic marked this conversation as resolved.
Outdated
case 'application/json':
$query = json_encode($params);
break;
Expand Down Expand Up @@ -170,23 +170,23 @@ public function call(string $method, string $path = '', array $headers = [], arr
$responseType = $responseHeaders['Content-Type'] ?? '';
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);

switch(substr($responseType, 0, strpos($responseType, ';'))) {
switch (substr($responseType, 0, strpos($responseType, ';'))) {
case 'application/json':
$responseBody = json_decode($responseBody, true);
break;
}

if (curl_errno($ch)) {
throw new \Exception(curl_error($ch));
throw new \Exception(curl_error($ch), $responseStatus);
}

curl_close($ch);

if ($responseStatus >= 400) {
if (is_array($responseBody)) {
throw new \Exception(json_encode($responseBody));
throw new \Exception(json_encode($responseBody), $responseStatus);
} else {
throw new \Exception($responseStatus.': '.$responseBody);
throw new \Exception($responseStatus.': '.$responseBody, $responseStatus);
}
}

Expand Down Expand Up @@ -225,5 +225,8 @@ protected function logError(Exception $e)
Console::error('[Error] Message: '.$e->getMessage());
Console::error('[Error] File: '.$e->getFile());
Console::error('[Error] Line: '.$e->getLine());

Comment thread
PineappleIOnic marked this conversation as resolved.
Outdated
Console::error('[Error] Trace: ');
Console::error($e->getTraceAsString());
}
}
1 change: 0 additions & 1 deletion src/Analytics/Adapter/ActiveCampaign.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ public function deleteAccount(string $accountId): bool
public function syncAssociation(string $accountId, string $contactId, string $role = ''): bool
{
// See if the association already exists

try {
$result = $this->call('GET', '/api/3/accountContacts', [], [
'filters[account]' => $accountId,
Expand Down
314 changes: 314 additions & 0 deletions src/Analytics/Adapter/HubSpot.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
<?php

namespace Utopia\Analytics\Adapter;

use Utopia\Analytics\Adapter;
use Utopia\Analytics\Event;

class HubSpot extends Adapter
{
/**
* Endpoint for MixPanel Events
*/
public string $endpoint = 'https://api.hubapi.com';

public function __construct(string $token)
{
$this->headers = [
'Authorization' => 'Bearer '.$token,
];
}

/**
* Creates an Event on the remote analytics platform.
*/
public function send(Event $event): bool
{
if (! $this->enabled) {
return false;
}

// HubSpot event tracking isn't possible due to their chrome based extention system
return true;
Comment thread
PineappleIOnic marked this conversation as resolved.
Outdated
}

public function validate(Event $event): bool
{
if (! $this->enabled) {
return false;
}

// HubSpot event tracking isn't possible due to their chrome based extention system
return true;
Comment thread
PineappleIOnic marked this conversation as resolved.
Outdated
}

/**
* Gets the name of the adapter.
*/
public function getName(): string
{
return 'HubSpot';
}

/**
* Checks if a contact exists by the email ID. Returns the User ID if it exists and false if it doesn't.
*/
public function contactExists(string $email): bool|int
{
try {
$result = $this->call('POST', '/crm/v3/objects/contacts/search', [
'Content-Type' => 'application/json',
], [
'filterGroups' => [[
'filters' => [
[
'value' => $email,
'propertyName' => 'email',
'operator' => 'EQ',
],
],
], ],
]);

$result = json_decode($result, true);

if ($result && $result['total'] > 0 && count($result['results']) > 0) {
return $result['results'][0]['id'];
} else {
return false;
}
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Create a contact
*/
public function createContact(string $email, string $firstName = '', string $lastName = '', string $phone = ''): bool
{
$body = ['properties' => [
'email' => $email,
'firstname' => $firstName,
'lastname' => $lastName,
'phone' => $phone,
]];

try {
$this->call('POST', '/crm/v3/objects/contacts', [
'Content-Type' => 'application/json',
], $body);

return true;
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Update contact
*/
public function updateContact(string $contactId, string $email, string $firstName = '', string $lastName = '', string $phone = ''): bool
{
$body = [
'email' => $email,
'firstname' => $firstName,
'lastname' => $lastName,
'phone' => $phone,
];

try {
$this->call('PATCH', '/crm/v3/objects/contacts/'.$contactId, [
'Content-Type' => 'application/json',
], $body);

return true;
} catch (\Exception $e) {
if ($e->getCode() == 400) {
// No changes to make
return true;
}

$this->logError($e);

return false;
}
}

/**
* Delete a contact
*/
public function deleteContact(string $email): bool
{
$contact = $this->contactExists($email);

if (! $contact) {
return false;
}

try {
$this->call('DELETE', '/crm/v3/objects/contacts/'.$contact, [
'Content-Type' => 'application/json',
]);

return true;
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Account Exists
*/
public function accountExists(string $name): bool|int
{
try {
$result = $this->call('POST', '/crm/v3/objects/companies/search', [
'Content-Type' => 'application/json',
], [
'filterGroups' => [[
'filters' => [
[
'value' => $name,
'propertyName' => 'name',
'operator' => 'EQ',
],
],
]],
]);

$result = json_decode($result, true);

if ($result && $result['total'] > 0 && count($result['results']) > 0) {
return $result['results'][0]['id'];
} else {
return false;
}
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Create an account
*/
public function createAccount(string $name, string $url = ''): bool
{
$body = ['properties' => [
'name' => $name,
'domain' => $url,
]];

try {
$this->call('POST', '/crm/v3/objects/companies', [
'Content-Type' => 'application/json',
], $body);

return true;
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Update an account
*/
public function updateAccount(string $accountId, string $name, string $url = '', int $ownerId = 1, array $fields = []): bool
{
$body = [
'name' => $name,
'domain' => $url,
];

try {
$this->call('PATCH', '/crm/v3/objects/companies/'.$accountId, [
'Content-Type' => 'application/json',
], $body);

return true;
} catch (\Exception $e) {
if ($e->getCode() == 400) {
// No changes to make
return true;
}

$this->logError($e);

return false;
}
}

/**
* Delete an account
*/
public function deleteAccount(string $accountId): bool
{
try {
$this->call('DELETE', '/crm/v3/objects/companies/'.$accountId, [
'Content-Type' => 'application/json',
]);

return true;
} catch (\Exception $e) {
$this->logError($e);

return false;
}
}

/**
* Sync an association
*
* Creates an association if it doesn't exist and updates it if it does
*/
public function syncAssociation(string $accountId, string $contactId, string $role = ''): bool
{
// See if the association already exists

try {
$response = $this->call('GET', '/crm/v4/objects/contact/'.$accountId.'/associations/company');

$response = json_decode($response, true);

$associationId = null;

foreach ($response['results'] as $association) {
if ($association['from']['id'] == $contactId) {
$associationId = $association['id'];
}
}

if (empty($associationId)) {
// Create the association
$this->call('PUT', '/crm/v4/objects/contact/'.$contactId.'/associations/default/company/'.$accountId, [
'Content-Type' => 'application/json',
]);
} else {
// Delete and recreate the association
$this->call('DELETE', '/crm/v4/objects/contact/'.$contactId.'/associations/company/'.$accountId, [
'Content-Type' => 'application/json',
]);

$this->call('PUT', '/crm/v4/objects/contact/'.$contactId.'/associations/default/company/'.$accountId, [
'Content-Type' => 'application/json',
]);
}
} catch (\Exception $e) {
$this->logError($e);

return false;
}

return true;
}
}
Loading