Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
239 changes: 239 additions & 0 deletions backend/Actions/MondayCom/MondayComController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
<?php

/**
* MondayCom Integration
*/

namespace BitApps\Integrations\Actions\MondayCom;

use BitApps\Integrations\Core\Util\HttpHelper;
use WP_Error;

class MondayComController
{
private const API_URL = 'https://api.monday.com/v2';

private const API_VERSION = '2023-10';

public static function authentication($requestParams)
{
if (empty($requestParams->apiToken)) {
wp_send_json_error(__('API Token is empty', 'bit-integrations'), 400);
}

$query = 'query { me { id name email } }';
$response = self::request($requestParams->apiToken, $query);

if (!self::hasErrors($response) && isset($response->data->me->id)) {
wp_send_json_success(__('Authentication successful', 'bit-integrations'), 200);
}

wp_send_json_error(self::errorMessage($response, __('Authentication failed', 'bit-integrations')), 400);
}

public function getBoards($requestParams)
{
self::validateToken($requestParams);

$query = <<<'GRAPHQL'
query ($limit: Int) {
boards (limit: $limit) {
id
name
}
}
GRAPHQL;
$response = self::request($requestParams->apiToken, $query, ['limit' => 100]);

if (self::hasErrors($response) || !isset($response->data->boards)) {
wp_send_json_error(self::errorMessage($response, __('Boards fetching failed', 'bit-integrations')), 400);
}

$boards = array_map(
fn ($b) => (object) ['id' => $b->id, 'name' => $b->name],
$response->data->boards
);

wp_send_json_success($boards, 200);
}

public function getGroups($requestParams)
{
self::validateToken($requestParams);
if (empty($requestParams->boardId)) {
wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400);
}

$query = <<<'GRAPHQL'
query ($boardIds: [ID!]) {
boards (ids: $boardIds) {
groups {
id
title
}
}
}
GRAPHQL;
$response = self::request($requestParams->apiToken, $query, ['boardIds' => [(string) $requestParams->boardId]]);

if (self::hasErrors($response) || !isset($response->data->boards[0]->groups)) {
wp_send_json_error(self::errorMessage($response, __('Groups fetching failed', 'bit-integrations')), 400);
}

$groups = array_map(
fn ($g) => (object) ['id' => $g->id, 'name' => $g->title],
$response->data->boards[0]->groups
);

wp_send_json_success($groups, 200);
}

public function getColumns($requestParams)
{
self::validateToken($requestParams);
if (empty($requestParams->boardId)) {
wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400);
}

$query = <<<'GRAPHQL'
query ($boardIds: [ID!]) {
boards (ids: $boardIds) {
columns {
id
title
type
}
}
}
GRAPHQL;
$response = self::request($requestParams->apiToken, $query, ['boardIds' => [(string) $requestParams->boardId]]);

if (self::hasErrors($response) || !isset($response->data->boards[0]->columns)) {
wp_send_json_error(self::errorMessage($response, __('Columns fetching failed', 'bit-integrations')), 400);
}

$columns = [];
foreach (reset($response->data->boards)->columns as $column) {
if ($column->type !== 'file') {
$columns[] = (object) [
'key' => $column->id,
'label' => $column->title,
'type' => $column->type,
'required' => false,
];
}
}

wp_send_json_success($columns, 200);
}

public function getItems($requestParams)
{
self::validateToken($requestParams);
if (empty($requestParams->boardId)) {
wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400);
}

$query = <<<'GRAPHQL'
query ($boardIds: [ID!], $limit: Int) {
boards (ids: $boardIds) {
items_page (limit: $limit) {
items {
id
name
}
}
}
}
GRAPHQL;
$response = self::request(
$requestParams->apiToken,
$query,
[
'boardIds' => [(string) $requestParams->boardId],
'limit' => 100,
]
);

if (self::hasErrors($response) || !isset($response->data->boards[0]->items_page->items)) {
wp_send_json_error(self::errorMessage($response, __('Items fetching failed', 'bit-integrations')), 400);
}

$items = array_map(
fn ($i) => (object) ['id' => $i->id, 'name' => $i->name],
$response->data->boards[0]->items_page->items
);

wp_send_json_success($items, 200);
}

public function execute($integrationData, $fieldValues)
{
$integrationDetails = $integrationData->flow_details;
$integId = $integrationData->id;
$fieldMap = $integrationDetails->field_map ?? [];
$apiToken = $integrationDetails->apiToken ?? '';

if (empty($apiToken)) {
return new WP_Error('REQ_FIELD_EMPTY', __('API Token is required for Monday.com api', 'bit-integrations'));
}

$recordApiHelper = new RecordApiHelper($integrationDetails, $integId, $apiToken);
$response = $recordApiHelper->execute($fieldValues, $fieldMap);

if (is_wp_error($response)) {
return $response;
}

return $response;
}

private static function validateToken($requestParams)
{
if (empty($requestParams->apiToken)) {
wp_send_json_error(__('API Token is empty', 'bit-integrations'), 400);
}
}

private static function setHeaders($apiToken)
{
return [
'Authorization' => $apiToken,
'Content-Type' => 'application/json',
'API-Version' => self::API_VERSION,
];
}

private static function request($apiToken, $query, $variables = [])
{
$body = ['query' => $query];

if (!empty($variables)) {
$body['variables'] = $variables;
}

return HttpHelper::post(self::API_URL, wp_json_encode($body), self::setHeaders($apiToken));
}

private static function hasErrors($response)
{
return is_wp_error($response) || !empty($response->errors) || !empty($response->error);
}

private static function errorMessage($response, $fallback)
{
if (is_wp_error($response)) {
return $response->get_error_message();
}

if (!empty($response->errors[0]->message)) {
return $response->errors[0]->message;
}

if (!empty($response->error)) {
return \is_string($response->error) ? $response->error : wp_json_encode($response->error);
}

return $fallback;
}
}
151 changes: 151 additions & 0 deletions backend/Actions/MondayCom/RecordApiHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

/**
* MondayCom Record Api
*/

namespace BitApps\Integrations\Actions\MondayCom;

use BitApps\Integrations\Config;
use BitApps\Integrations\Core\Util\Common;
use BitApps\Integrations\Core\Util\Hooks;
use BitApps\Integrations\Log\LogHandler;

class RecordApiHelper
{
private $integrationDetails;

private $integrationId;

private $apiToken;

private $type;

private $typeName;

public function __construct($integrationDetails, $integId, $apiToken)
{
$this->integrationDetails = $integrationDetails;
$this->integrationId = $integId;
$this->apiToken = $apiToken;
}

public function handleFilterResponse($response)
{
if ($response) {
return $response;
}

// translators: %s: Placeholder value
return (object) ['error' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro')];
}

public function generateReqDataFromFieldMap($fieldValues, $fieldMap)
{
$dataFinal = [];
foreach ($fieldMap as $item) {
$triggerValue = $item->formField ?? '';
$actionValue = $item->mondayComField ?? '';

if (empty($actionValue)) {
continue;
}

if ($triggerValue === 'custom') {
$dataFinal[$actionValue] = Common::replaceFieldWithValue($item->customValue ?? '', $fieldValues);
} elseif (!empty($triggerValue)) {
$dataFinal[$actionValue] = $fieldValues[$triggerValue] ?? '';
}
}

return $dataFinal;
}

public function execute($fieldValues, $fieldMap)
{
$fieldData = $this->generateReqDataFromFieldMap($fieldValues, $fieldMap);
$mainAction = $this->integrationDetails->mainAction ?? '';
$apiResponse = null;
$responseType = null;

$this->type = 'item';
$this->typeName = $mainAction;

switch ($mainAction) {
case 'create_item':
$this->type = 'item';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_item'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'update_item':
$this->type = 'item';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_update_item'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'create_subitem':
$this->type = 'subitem';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_subitem'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'move_item_to_group':
$this->type = 'item';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_move_item_to_group'), false, $fieldData, $this->apiToken);
Comment thread
RishadAlam marked this conversation as resolved.

break;
case 'archive_item':
$this->type = 'item';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_item'), false, $fieldData, $this->apiToken);

break;
case 'delete_item':
$this->type = 'item';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_delete_item'), false, $fieldData, $this->apiToken);

break;
case 'archive_board':
$this->type = 'board';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->apiToken);
Comment thread
RishadAlam marked this conversation as resolved.

break;
case 'archive_group':
$this->type = 'group';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_group'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'delete_group':
$this->type = 'group';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_delete_group'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'create_group':
$this->type = 'group';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_group'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'duplicate_group':
$this->type = 'group';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_duplicate_group'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
case 'create_column':
$this->type = 'column';
$apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_column'), false, $fieldData, $this->integrationDetails, $this->apiToken);

break;
default:
$apiResponse = null;
}

$apiResponse = $this->handleFilterResponse($apiResponse);
$responseType = $this->hasErrors($apiResponse) || !isset($apiResponse->data) ? 'error' : 'success';

LogHandler::save($this->integrationId, wp_json_encode(['type' => $this->type, 'type_name' => $this->typeName]), $responseType, wp_json_encode($apiResponse));

return $apiResponse;
}

private function hasErrors($response)
{
return is_wp_error($response) || !empty($response->errors) || !empty($response->error);
}
}
Loading
Loading