474 lines
13 KiB
PHP
474 lines
13 KiB
PHP
<?php
|
|
|
|
use CRM_TwingleCampaign_ExtensionUtil as E;
|
|
|
|
|
|
class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
|
|
|
private $apiKey;
|
|
|
|
private $baseUrl = '.twingle.de/api/';
|
|
|
|
private $protocol = 'https://';
|
|
|
|
private $organisationId;
|
|
|
|
private $limit;
|
|
|
|
private $extensionName;
|
|
|
|
/**
|
|
* ## TwingleApiCall constructor
|
|
*
|
|
* @param $apiKey
|
|
*
|
|
* @param int $limit
|
|
* Limit for the number of events that should get requested per call to the
|
|
* Twingle API
|
|
*
|
|
* @throws API_Exception
|
|
*/
|
|
public function __construct(string $apiKey, int $limit = 20) {
|
|
$this->apiKey = $apiKey;
|
|
$this->limit = $limit;
|
|
$this->extensionName = E::LONG_NAME;
|
|
|
|
// Try to retrieve organisation id from cache
|
|
$this->organisationId = Civi::cache()
|
|
->get('twinglecampaign_organisation_id');
|
|
|
|
// else: retrieve organisation id via Twingle api
|
|
if (NULL === $this->organisationId) {
|
|
|
|
$curl = curl_init($this->protocol . 'organisation' . $this->baseUrl);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
|
"x-access-code: $apiKey",
|
|
'Content-Type: application/json',
|
|
]);
|
|
|
|
$response = json_decode(curl_exec($curl), TRUE);
|
|
curl_close($curl);
|
|
|
|
if (empty($response)) {
|
|
// Delete api key from cache
|
|
Civi::cache()->delete('twinglecampaign_twingle_api');
|
|
// Throw exception
|
|
throw new API_Exception(
|
|
"Twingle API call failed. Please check your api key.");
|
|
}
|
|
$this->organisationId = array_column($response, 'id')[0];
|
|
Civi::cache('long')->set('twinglecampaign_organisation_id',
|
|
$this->organisationId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ## Get project from Twingle
|
|
* If the **$id** parameter is empty, this function returns all projects for
|
|
* this organisation.
|
|
*
|
|
* If the **$id** parameter is provided, this function returns a single
|
|
* project.
|
|
*
|
|
* @param int|null $projectId
|
|
*
|
|
* @return array|false
|
|
* @throws Exception
|
|
*/
|
|
public function getProject(int $projectId = NULL): ?array {
|
|
|
|
// If no project id is provided, return all projects
|
|
if (empty($projectId)) {
|
|
$response = [];
|
|
$projects = $this->curlGet($this->protocol . 'project' .
|
|
$this->baseUrl . 'by-organisation/' . $this->organisationId);
|
|
foreach ($projects as $project) {
|
|
$response[] = $this->getProject($project['id']);
|
|
}
|
|
return $response;
|
|
}
|
|
// If a project id is provided, return only one project
|
|
else {
|
|
|
|
// Get all general project information
|
|
$project = $this->curlGet($this->protocol . 'project' .
|
|
$this->baseUrl . $projectId);
|
|
|
|
// Get project options
|
|
$project['project_options'] = $this->getProjectOptions($projectId);
|
|
|
|
// Get project payment methods
|
|
$project['payment_methods'] =
|
|
$this->getProjectPaymentMethods($projectId);
|
|
|
|
// Set last update time
|
|
$project['last_update'] = max(
|
|
$project['last_update'],
|
|
$project['project_options']['last_update'],
|
|
$project['payment_methods']['updated_at']
|
|
);
|
|
unset($project['project_options']['last_update']);
|
|
unset($project['payment_methods']['updated_at']);
|
|
|
|
return $project;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ## Push project to Twingle
|
|
* Sends a curl post call to Twingle to update an existing project.
|
|
*
|
|
* Returns an array with all project values.
|
|
*
|
|
* @param array $project
|
|
* The project values array that should get pushed to Twingle
|
|
*
|
|
* @return array
|
|
* @throws \Exception
|
|
*/
|
|
public function pushProject(array $project): array {
|
|
|
|
if (isset($project['project_options'])) {
|
|
$projectOptions = $project['project_options'];
|
|
unset($project['project_options']);
|
|
}
|
|
if (isset($project['payment_methods'])) {
|
|
$paymentMethods = $project['payment_methods'];
|
|
unset($project['payment_methods']);
|
|
}
|
|
|
|
try {
|
|
if (!isset($project['id'])) {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . 'by-organisation/' .
|
|
$this->organisationId;
|
|
|
|
// Post project values
|
|
$updatedProject = $this->curlPost($url, $project);
|
|
|
|
$url = $this->protocol . 'project' . $this->baseUrl .
|
|
$updatedProject['id'];
|
|
}
|
|
else {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . $project['id'];
|
|
|
|
// Post project values
|
|
$updatedProject = $this->curlPost($url, $project);
|
|
}
|
|
|
|
// Post project_options
|
|
if (isset($projectOptions)) {
|
|
$updatedProject['project_options'] =
|
|
$this->curlPost($url . '/options', $projectOptions);
|
|
}
|
|
else {
|
|
$updatedProject['project_options'] = $this->getProjectOptions($updatedProject['id']);
|
|
}
|
|
|
|
// Post payment_methods
|
|
if (isset ($paymentMethods)) {
|
|
$this->curlPost($url . '/payment-methods', $paymentMethods);
|
|
}
|
|
$updatedProject['payment_methods'] =
|
|
$this->getProjectPaymentMethods($updatedProject['id']);
|
|
|
|
|
|
// Set last update time
|
|
$updatedProject['last_update'] = max(
|
|
$updatedProject['last_update'],
|
|
$updatedProject['project_options']['last_update'],
|
|
$updatedProject['payment_methods']['updated_at']
|
|
);
|
|
unset($updatedProject['project_options']['last_update']);
|
|
unset($updatedProject['payment_methods']['updated_at']);
|
|
|
|
return $updatedProject;
|
|
}
|
|
catch
|
|
(Exception $e) {
|
|
throw new Exception(
|
|
E::SHORT_NAME . 'Call to Twingle API failed: ' .
|
|
$e->getMessage()
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Get event from Twingle
|
|
* Returns all events for the provided **$projectId** or a single event if an
|
|
* **$eventId** is provided, too.
|
|
*
|
|
* @param int $projectId
|
|
* @param null|int $eventId
|
|
*
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getEvent(int $projectId, int $eventId = NULL): array {
|
|
$result = [];
|
|
|
|
// Construct url for curl
|
|
$url = empty($eventId)
|
|
? $this->protocol . 'project' . $this->baseUrl . $projectId . '/event'
|
|
: $this->protocol . 'project' . $this->baseUrl . $projectId . '/event/'
|
|
. $eventId;
|
|
|
|
$offset = 0;
|
|
$finished = FALSE;
|
|
|
|
// Get only as much results per call as configured in $this->limit
|
|
while (!$finished) {
|
|
$params = [
|
|
'orderby' => 'id',
|
|
'direction' => 'desc',
|
|
'limit' => $this->limit,
|
|
'offset' => $offset,
|
|
'image' => 'as-boolean',
|
|
'public' => 0,
|
|
];
|
|
$response = $this->curlGet($url, $params);
|
|
|
|
// If no $eventId was given, expect one or more events.
|
|
// Store the events, increase the offset and ask again until there
|
|
// are no more events incoming.
|
|
if (!$eventId) {
|
|
$result = array_merge($result, $response['data']);
|
|
$offset = $offset + $this->limit;
|
|
$finished = count($response['data']) < $this->limit;
|
|
}
|
|
// If $eventId was given, expect only one event
|
|
else {
|
|
// If the response array contains 'message', the $eventId does not exist
|
|
if (!$response['message']) {
|
|
$result = $response;
|
|
}
|
|
$finished = TRUE;
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* ## Get project embed data
|
|
* Get embed data for a specific project.
|
|
*
|
|
* @param $projectId
|
|
*
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function getProjectEmbedData($projectId): array {
|
|
|
|
$result = $this->getProject($projectId);
|
|
|
|
if ($result['embed']) {
|
|
// Include counter url into embed data
|
|
$result['embed']['counter'] = $result['counter-url']['url'];
|
|
|
|
return $result['embed'];
|
|
}
|
|
else {
|
|
throw new Exception(
|
|
"Could not get embed data for project $projectId."
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ## Get project options
|
|
* Gets all project options from the Twingle API
|
|
*
|
|
* @param $projectId
|
|
*
|
|
* @return array
|
|
* @throws \Exception
|
|
*/
|
|
public function getProjectOptions($projectId): array {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . $projectId . '/options';
|
|
return $this->curlGet($url);
|
|
}
|
|
|
|
/**
|
|
* ## Get project payment methods
|
|
* Gets all project payment methods from the Twingle API
|
|
*
|
|
* @param $projectId
|
|
*
|
|
* @return array
|
|
* @throws \Exception
|
|
*/
|
|
public function getProjectPaymentMethods($projectId): array {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . $projectId
|
|
. '/payment-methods';
|
|
return $this->curlGet($url);
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Delete Project
|
|
* Sends a DELETE cURL and returns the result array.
|
|
*
|
|
* @param int $projectId
|
|
*
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public function deleteProject(int $projectId): bool {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . $projectId;
|
|
return $this->curlDelete($url);
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Delete Event
|
|
* Sends a DELETE cURL and returns TRUE id deletion was successful.
|
|
*
|
|
* *NOTE:* It's only possible to delete one event at a time.
|
|
*
|
|
* @param int $projectId
|
|
* @param int $eventId
|
|
*
|
|
* @return bool
|
|
* @throws Exception
|
|
*/
|
|
public function deleteEvent(int $projectId, int $eventId): bool {
|
|
$url = $this->protocol . 'project' . $this->baseUrl . $projectId .
|
|
'/event/' . $eventId;
|
|
return $this->curlDelete($url);
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Send a GET cURL
|
|
* Sends a GET cURL and returns the result array.
|
|
*
|
|
* @param $url
|
|
* The destination url
|
|
*
|
|
* @param null $params
|
|
* The parameters you want to send (optional)
|
|
*
|
|
* @return array
|
|
* Returns the result array of the curl or FALSE, if the curl failed
|
|
* @throws Exception
|
|
*/
|
|
private
|
|
function curlGet($url, $params = NULL): array {
|
|
if (!empty($params)) {
|
|
$url = $url . '?' . http_build_query($params);
|
|
}
|
|
$curl = curl_init($url);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER,
|
|
[
|
|
"x-access-code: $this->apiKey",
|
|
'Content-Type: application/json',
|
|
]
|
|
);
|
|
$response = json_decode(curl_exec($curl), TRUE);
|
|
$curl_status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
curl_close($curl);
|
|
if ($response === FALSE) {
|
|
throw new Exception('GET curl failed');
|
|
}
|
|
if ($curl_status_code == 404) {
|
|
throw new Exception('http status code 404 (not found)');
|
|
}
|
|
elseif ($curl_status_code == 500) {
|
|
throw new Exception('https status code 500 (internal error)');
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Send a POST cURL
|
|
* Sends a POST cURL and returns the result array.
|
|
*
|
|
* @param $url
|
|
* The destination url
|
|
*
|
|
* @param $data
|
|
* The data that should get send
|
|
*
|
|
* @return array
|
|
* Returns the result array of the curl or FALSE, if the curl failed
|
|
* @throws Exception
|
|
*/
|
|
private
|
|
function curlPost($url, $data): array {
|
|
$curl = curl_init($url);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
|
curl_setopt($curl, CURLOPT_POST, TRUE);
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER,
|
|
[
|
|
"x-access-code: $this->apiKey",
|
|
'Content-Type: application/json',
|
|
]
|
|
);
|
|
$json = json_encode($data);
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
|
|
$response = json_decode(curl_exec($curl), TRUE);
|
|
$curl_status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
curl_close($curl);
|
|
if ($response === FALSE) {
|
|
throw new Exception('POST curl failed');
|
|
}
|
|
if ($curl_status_code == 404) {
|
|
throw new Exception('http status code 404 (not found)');
|
|
}
|
|
elseif ($curl_status_code == 500) {
|
|
throw new Exception('https status code 500 (internal error)');
|
|
}
|
|
if (sizeof($response) == 1 && isset($response['message'])) {
|
|
throw new Exception($response['message']);
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
|
|
/**
|
|
* ## Send a DELETE cURL
|
|
* Sends a DELETE cURL and returns the result array.
|
|
*
|
|
* @param $url
|
|
* The parameters you want to send
|
|
*
|
|
* @param $params
|
|
* The data that should get send
|
|
*
|
|
* @return bool
|
|
* Returns the result array of the curl or FALSE, if the curl failed
|
|
* @throws Exception
|
|
*/
|
|
private
|
|
function curlDelete($url, $params = NULL): bool {
|
|
if (!empty($params)) {
|
|
$url = $url . '?' . http_build_query($params);
|
|
}
|
|
$curl = curl_init($url);
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
|
|
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
|
curl_setopt($curl, CURLOPT_HTTPHEADER,
|
|
[
|
|
"x-access-code: $this->apiKey",
|
|
'Content-Type: application/json',
|
|
]
|
|
);
|
|
$response = json_decode(curl_exec($curl), TRUE);
|
|
$curl_status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
curl_close($curl);
|
|
if ($response === FALSE) {
|
|
throw new Exception('DELETE curl failed');
|
|
}
|
|
if ($curl_status_code == 404) {
|
|
throw new Exception('http status code 404 (not found)');
|
|
}
|
|
elseif ($curl_status_code == 500) {
|
|
throw new Exception('https status code 500 (internal error)');
|
|
}
|
|
return ($curl_status_code == 200);
|
|
}
|
|
|
|
}
|