✨️ implement validation of TwingleProject settings
This commit is contained in:
parent
060f7ec2dc
commit
34e2e77d83
7 changed files with 652 additions and 183 deletions
|
@ -33,7 +33,7 @@ abstract class CRM_TwingleCampaign_BAO_Campaign {
|
||||||
* @param array $values
|
* @param array $values
|
||||||
* @param int|null $id
|
* @param int|null $id
|
||||||
*/
|
*/
|
||||||
protected function __construct(array $values, int $id = NULL) {
|
protected function __construct(array $values = [], int $id = NULL) {
|
||||||
|
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
$tmpClassName = explode('_', get_class($this));
|
$tmpClassName = explode('_', get_class($this));
|
||||||
|
|
|
@ -129,10 +129,14 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
*/
|
*/
|
||||||
public function pushProject(array $project): array {
|
public function pushProject(array $project): array {
|
||||||
|
|
||||||
|
if (isset($project['project_options'])) {
|
||||||
$projectOptions = $project['project_options'];
|
$projectOptions = $project['project_options'];
|
||||||
unset($project['project_options']);
|
unset($project['project_options']);
|
||||||
|
}
|
||||||
|
if (isset($project['payment_methods'])) {
|
||||||
$paymentMethods = $project['payment_methods'];
|
$paymentMethods = $project['payment_methods'];
|
||||||
unset($project['payment_methods']);
|
unset($project['payment_methods']);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!isset($project['id'])) {
|
if (!isset($project['id'])) {
|
||||||
|
@ -153,14 +157,22 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post project_options
|
// Post project_options
|
||||||
|
if (isset($projectOptions)) {
|
||||||
$updatedProject['project_options'] =
|
$updatedProject['project_options'] =
|
||||||
$this->curlPost($url . '/options', $projectOptions);
|
$this->curlPost($url . '/options', $projectOptions);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$updatedProject['project_options'] = $this->getProjectOptions($updatedProject['id']);
|
||||||
|
}
|
||||||
|
|
||||||
// Post payment_methods
|
// Post payment_methods
|
||||||
|
if (isset ($paymentMethods)) {
|
||||||
$this->curlPost($url . '/payment-methods', $paymentMethods);
|
$this->curlPost($url . '/payment-methods', $paymentMethods);
|
||||||
|
}
|
||||||
$updatedProject['payment_methods'] =
|
$updatedProject['payment_methods'] =
|
||||||
$this->getProjectPaymentMethods($updatedProject['id']);
|
$this->getProjectPaymentMethods($updatedProject['id']);
|
||||||
|
|
||||||
|
|
||||||
// Set last update time
|
// Set last update time
|
||||||
$updatedProject['last_update'] = max(
|
$updatedProject['last_update'] = max(
|
||||||
$updatedProject['last_update'],
|
$updatedProject['last_update'],
|
||||||
|
@ -171,14 +183,14 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
unset($updatedProject['payment_methods']['updated_at']);
|
unset($updatedProject['payment_methods']['updated_at']);
|
||||||
|
|
||||||
return $updatedProject;
|
return $updatedProject;
|
||||||
} catch (Exception $e) {
|
}
|
||||||
|
catch
|
||||||
|
(Exception $e) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
E::SHORT_NAME . 'Call to Twingle API failed: ' .
|
E::SHORT_NAME . 'Call to Twingle API failed: ' .
|
||||||
$e->getMessage()
|
$e->getMessage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,6 +278,7 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
/**
|
/**
|
||||||
* ## Get project options
|
* ## Get project options
|
||||||
* Gets all project options from the Twingle API
|
* Gets all project options from the Twingle API
|
||||||
|
*
|
||||||
* @param $projectId
|
* @param $projectId
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
@ -279,6 +292,7 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
/**
|
/**
|
||||||
* ## Get project payment methods
|
* ## Get project payment methods
|
||||||
* Gets all project payment methods from the Twingle API
|
* Gets all project payment methods from the Twingle API
|
||||||
|
*
|
||||||
* @param $projectId
|
* @param $projectId
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
@ -360,7 +374,8 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
}
|
}
|
||||||
if ($curl_status_code == 404) {
|
if ($curl_status_code == 404) {
|
||||||
throw new Exception('http status code 404 (not found)');
|
throw new Exception('http status code 404 (not found)');
|
||||||
} elseif ($curl_status_code == 500) {
|
}
|
||||||
|
elseif ($curl_status_code == 500) {
|
||||||
throw new Exception('https status code 500 (internal error)');
|
throw new Exception('https status code 500 (internal error)');
|
||||||
}
|
}
|
||||||
return $response;
|
return $response;
|
||||||
|
@ -402,7 +417,8 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
}
|
}
|
||||||
if ($curl_status_code == 404) {
|
if ($curl_status_code == 404) {
|
||||||
throw new Exception('http status code 404 (not found)');
|
throw new Exception('http status code 404 (not found)');
|
||||||
} elseif ($curl_status_code == 500) {
|
}
|
||||||
|
elseif ($curl_status_code == 500) {
|
||||||
throw new Exception('https status code 500 (internal error)');
|
throw new Exception('https status code 500 (internal error)');
|
||||||
}
|
}
|
||||||
if (sizeof($response) == 1 && isset($response['message'])) {
|
if (sizeof($response) == 1 && isset($response['message'])) {
|
||||||
|
@ -448,7 +464,8 @@ class CRM_TwingleCampaign_BAO_TwingleApiCall {
|
||||||
}
|
}
|
||||||
if ($curl_status_code == 404) {
|
if ($curl_status_code == 404) {
|
||||||
throw new Exception('http status code 404 (not found)');
|
throw new Exception('http status code 404 (not found)');
|
||||||
} elseif ($curl_status_code == 500) {
|
}
|
||||||
|
elseif ($curl_status_code == 500) {
|
||||||
throw new Exception('https status code 500 (internal error)');
|
throw new Exception('https status code 500 (internal error)');
|
||||||
}
|
}
|
||||||
return ($curl_status_code == 200);
|
return ($curl_status_code == 200);
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CRM_TwingleCampaign_BAO_TwingleCampaign {
|
||||||
*
|
*
|
||||||
* @throws \CiviCRM_API3_Exception
|
* @throws \CiviCRM_API3_Exception
|
||||||
*/
|
*/
|
||||||
public function __construct(array $values, int $id = NULL) {
|
public function __construct(array $values = [], int $id = NULL) {
|
||||||
|
|
||||||
$this->prefix = 'twingle_campaign_';
|
$this->prefix = 'twingle_campaign_';
|
||||||
$this->id = $id ?? NULL;
|
$this->id = $id ?? NULL;
|
||||||
|
|
|
@ -19,7 +19,7 @@ class CRM_TwingleCampaign_BAO_TwingleEvent extends Campaign {
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function __construct(array $event, int $id = NULL) {
|
public function __construct(array $event = [], int $id = NULL) {
|
||||||
parent::__construct($event, $id);
|
parent::__construct($event, $id);
|
||||||
|
|
||||||
$this->prefix = 'twingle_event_';
|
$this->prefix = 'twingle_event_';
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
* @param int|null $id
|
* @param int|null $id
|
||||||
* CiviCRM Campaign id
|
* CiviCRM Campaign id
|
||||||
*/
|
*/
|
||||||
public function __construct(array $values, int $id = NULL) {
|
public function __construct(array $values = [], int $id = NULL) {
|
||||||
parent::__construct($values, $id);
|
parent::__construct($values, $id);
|
||||||
|
|
||||||
$this->prefix = 'twingle_project_';
|
$this->prefix = 'twingle_project_';
|
||||||
|
@ -85,7 +85,9 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
* ## Int to bool
|
* ## Int to bool
|
||||||
* Changes all project values that are defined as CiviCRM 'Boolean' types
|
* Changes all project values that are defined as CiviCRM 'Boolean' types
|
||||||
* from strings to booleans.
|
* from strings to booleans.
|
||||||
|
*
|
||||||
* @param array $values
|
* @param array $values
|
||||||
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function intToBool(array &$values) {
|
private function intToBool(array &$values) {
|
||||||
|
@ -104,7 +106,10 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
}
|
}
|
||||||
elseif (in_array($key, $boolArrays)) {
|
elseif (in_array($key, $boolArrays)) {
|
||||||
foreach ($values[$key] as $_key => $_value) {
|
foreach ($values[$key] as $_key => $_value) {
|
||||||
if (is_numeric($_value) && $_value < 2 || empty($_value)) {
|
if (is_bool($_value)) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
elseif (is_numeric($_value) && $_value < 2 || empty($_value)) {
|
||||||
$values[$key][$_key] = (bool) $_value;
|
$values[$key][$_key] = (bool) $_value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -122,7 +127,9 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
* ## Int to bool
|
* ## Int to bool
|
||||||
* Changes all project values that are strings but originally came as integers
|
* Changes all project values that are strings but originally came as integers
|
||||||
* back to integers.
|
* back to integers.
|
||||||
|
*
|
||||||
* @param array $values
|
* @param array $values
|
||||||
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function strToInt(array &$values) {
|
private function strToInt(array &$values) {
|
||||||
|
@ -214,8 +221,33 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## Clone this TwingleProject
|
* ## Complement campaign values
|
||||||
|
* Complement existing campaign values with new ones
|
||||||
*
|
*
|
||||||
|
* @param array $arrayToComplement
|
||||||
|
*
|
||||||
|
* @overrides CRM_TwingleCampaign_BAO_Campaign
|
||||||
|
*/
|
||||||
|
public function complement(array $arrayToComplement) {
|
||||||
|
|
||||||
|
// Set all contact fields to false
|
||||||
|
if (
|
||||||
|
isset($arrayToComplement['values']['project_options']['contact_fields'])
|
||||||
|
) {
|
||||||
|
foreach (
|
||||||
|
$arrayToComplement['values']['project_options']['contact_fields']
|
||||||
|
as $key => $value
|
||||||
|
) {
|
||||||
|
$arrayToComplement['values']['project_options']['contact_fields'][$key]
|
||||||
|
= FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::complement($arrayToComplement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Clone this TwingleProject
|
||||||
* This method removes the id and the identifier from this instance and in
|
* This method removes the id and the identifier from this instance and in
|
||||||
* the next step it pushes the clone as a new project with the same values to
|
* the next step it pushes the clone as a new project with the same values to
|
||||||
* Twingle.
|
* Twingle.
|
||||||
|
@ -223,11 +255,163 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function clone() {
|
public function clone() {
|
||||||
$this->values['id'] = 0;
|
$this->values['id'] = '';
|
||||||
$this->values['identifier'] = 0;
|
$this->values['identifier'] = '';
|
||||||
$this->create(); // this will also trigger the postSave hook
|
$this->create(); // this will also trigger the postSave hook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Validate
|
||||||
|
* Validates project values and returns an array containing the result and
|
||||||
|
* another array with eventual error messages.
|
||||||
|
*
|
||||||
|
* @return array ['valid' => bool, 'messages' => array]
|
||||||
|
*/
|
||||||
|
public function validate(): array {
|
||||||
|
$valid = TRUE;
|
||||||
|
$messages = [];
|
||||||
|
|
||||||
|
// Validate email address
|
||||||
|
if (
|
||||||
|
!filter_var(
|
||||||
|
$this->values['project_options']['bcc_email_address'],
|
||||||
|
FILTER_VALIDATE_EMAIL
|
||||||
|
)
|
||||||
|
&& !empty($this->values['project_options']['bcc_email_address'])
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] = E::ts("BCC email invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate hexadecimal color fields
|
||||||
|
$colorFields =
|
||||||
|
[
|
||||||
|
'design_background_color',
|
||||||
|
'design_primary_color',
|
||||||
|
'design_font_color',
|
||||||
|
];
|
||||||
|
foreach ($colorFields as $colorField) {
|
||||||
|
if (
|
||||||
|
!empty($this->values['project_options'][$colorField]) &&
|
||||||
|
(
|
||||||
|
!(
|
||||||
|
ctype_xdigit($this->values['project_options'][$colorField]) ||
|
||||||
|
is_integer($this->values['project_options'][$colorField])
|
||||||
|
) ||
|
||||||
|
strlen((string) $this->values['project_options'][$colorField]) > 6
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Invalid hexadecimal value in color field: %1",
|
||||||
|
[1 => $colorField]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if donation values are integers and if proposed donation value
|
||||||
|
// lies between max and min values
|
||||||
|
if (
|
||||||
|
// Is integer and >= 0 or empty
|
||||||
|
(
|
||||||
|
empty($this->values['project_options']['donation_value_default']) ||
|
||||||
|
(
|
||||||
|
is_integer($this->values['project_options']['donation_value_default']) ||
|
||||||
|
ctype_digit($this->values['project_options']['donation_value_default'])
|
||||||
|
) && (
|
||||||
|
$this->values['project_options']['donation_value_default'] >= 0
|
||||||
|
)
|
||||||
|
) && (
|
||||||
|
empty($this->values['project_options']['donation_value_min']) ||
|
||||||
|
(
|
||||||
|
is_integer($this->values['project_options']['donation_value_min']) ||
|
||||||
|
ctype_digit($this->values['project_options']['donation_value_min'])
|
||||||
|
) && (
|
||||||
|
$this->values['project_options']['donation_value_max'] >= 0
|
||||||
|
)
|
||||||
|
) && (
|
||||||
|
empty($this->values['project_options']['donation_value_max']) ||
|
||||||
|
(
|
||||||
|
is_integer($this->values['project_options']['donation_value_max']) ||
|
||||||
|
ctype_digit($this->values['project_options']['donation_value_max'])
|
||||||
|
) && (
|
||||||
|
$this->values['project_options']['donation_value_max'] >= 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
// all empty
|
||||||
|
empty($this->values['project_options']['donation_value_default']) &&
|
||||||
|
empty($this->values['project_options']['donation_value_min']) &&
|
||||||
|
empty($this->values['project_options']['donation_value_max'])
|
||||||
|
) {
|
||||||
|
// nothing to validate
|
||||||
|
}
|
||||||
|
elseif (
|
||||||
|
// Max empty, min not empty
|
||||||
|
(!empty($this->values['project_options']['donation_value_min']) &&
|
||||||
|
empty($this->values['project_options']['donation_value_max'])) ||
|
||||||
|
// Max empty, default not empty
|
||||||
|
(!empty($this->values['project_options']['donation_value_default']) &&
|
||||||
|
empty($this->values['project_options']['donation_value_max']))
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Missing maximum donation value");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (
|
||||||
|
// Min >= Max
|
||||||
|
$this->values['project_options']['donation_value_min'] >=
|
||||||
|
$this->values['project_options']['donation_value_max']
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Maximum donation value must be higher than the minimum");
|
||||||
|
}
|
||||||
|
elseif (
|
||||||
|
// Default < min or default > max
|
||||||
|
$this->values['project_options']['donation_value_default'] <
|
||||||
|
$this->values['project_options']['donation_value_min'] ||
|
||||||
|
$this->values['project_options']['donation_value_default'] >
|
||||||
|
$this->values['project_options']['donation_value_max']
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Default donation value must lie in between maximum and minimum values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Donation values (Min, Max, Default) must be positive integers");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate sharing url
|
||||||
|
$urlFields =
|
||||||
|
[
|
||||||
|
'custom_css',
|
||||||
|
'share_url',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($urlFields as $urlField) {
|
||||||
|
if (!empty($this->values['project_options'][$urlField])) {
|
||||||
|
if (
|
||||||
|
!filter_var(
|
||||||
|
$this->values['project_options'][$urlField],
|
||||||
|
FILTER_VALIDATE_URL
|
||||||
|
) || empty($this->values['project_options'][$urlField])
|
||||||
|
) {
|
||||||
|
$valid = FALSE;
|
||||||
|
$messages[] =
|
||||||
|
E::ts("Invalid URL: %1", [1 => $urlField]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['valid' => $valid, 'messages' => $messages];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## Translate values between CiviCRM Campaigns and Twingle formats
|
* ## Translate values between CiviCRM Campaigns and Twingle formats
|
||||||
|
@ -246,7 +430,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static function formatValues(array &$values, string $direction) {
|
public
|
||||||
|
static function formatValues(array &$values, string $direction) {
|
||||||
|
|
||||||
if ($direction == self::IN) {
|
if ($direction == self::IN) {
|
||||||
|
|
||||||
|
@ -467,7 +652,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getResponse(string $status = NULL): array {
|
public
|
||||||
|
function getResponse(string $status = NULL): array {
|
||||||
$project_type = empty($this->values['type']) ? 'default' : $this->values['type'];
|
$project_type = empty($this->values['type']) ? 'default' : $this->values['type'];
|
||||||
$response =
|
$response =
|
||||||
[
|
[
|
||||||
|
@ -489,7 +675,8 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
*
|
*
|
||||||
* @return int|string|null
|
* @return int|string|null
|
||||||
*/
|
*/
|
||||||
public function lastUpdate() {
|
public
|
||||||
|
function lastUpdate(): ?int {
|
||||||
return self::getTimestamp($this->values['last_update']);
|
return self::getTimestamp($this->values['last_update']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,8 +687,72 @@ class CRM_TwingleCampaign_BAO_TwingleProject extends Campaign {
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getProjectId(): int {
|
public
|
||||||
|
function getProjectId(): int {
|
||||||
return (int) $this->values['id'];
|
return (int) $this->values['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the payment methods array of this project
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getValues(): array {
|
||||||
|
if (isset($this->values)) {
|
||||||
|
return $this->values;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the project options array of this project
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getOptions(): array {
|
||||||
|
if (isset($this->values['project_options'])) {
|
||||||
|
return $this->values['project_options'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the payment methods array of this project
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPaymentMethods(): array {
|
||||||
|
if (isset($this->values['payment_methods'])) {
|
||||||
|
return $this->values['payment_methods'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the payment methods array of this project
|
||||||
|
*/
|
||||||
|
public function deleteValues(): void {
|
||||||
|
unset ($this->values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the project options array of this project
|
||||||
|
*/
|
||||||
|
public function deleteOptions(): void {
|
||||||
|
unset($this->values['project_options']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ## Get the payment methods array of this project
|
||||||
|
*/
|
||||||
|
public function deletePaymentMethods(): void {
|
||||||
|
unset($this->values['payment_methods']);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,20 @@ function civicrm_api3_twingle_project_Sync(array $params): array {
|
||||||
// instantiate project
|
// instantiate project
|
||||||
$project = new TwingleProject($result, $id);
|
$project = new TwingleProject($result, $id);
|
||||||
|
|
||||||
|
// Send project information to Tingle and update project with the
|
||||||
|
// answer
|
||||||
|
$projectOptions = $project->getOptions();
|
||||||
|
$project->deleteOptions();
|
||||||
|
$paymentMethods = $project->getPaymentMethods();
|
||||||
|
$project->deletePaymentMethods();
|
||||||
|
$projectFromTwingle = $twingleApi->pushProject($project->export());
|
||||||
|
$project = new TwingleProject($projectFromTwingle, $project->getId());
|
||||||
|
$projectValues = $project->getValues();
|
||||||
|
$projectValues['project_options'] = $projectOptions;
|
||||||
|
$projectValues['payment_methods'] = $paymentMethods;
|
||||||
|
$project->update($projectValues);
|
||||||
|
$project->complement($projectFromTwingle);
|
||||||
|
|
||||||
// Push project to Twingle
|
// Push project to Twingle
|
||||||
return _pushProjectToTwingle($project, $twingleApi, $params);
|
return _pushProjectToTwingle($project, $twingleApi, $params);
|
||||||
}
|
}
|
||||||
|
@ -342,17 +356,19 @@ function _updateProjectLocally(array $project_from_twingle,
|
||||||
* @param \CRM_TwingleCampaign_BAO_TwingleProject $project
|
* @param \CRM_TwingleCampaign_BAO_TwingleProject $project
|
||||||
* @param \CRM_TwingleCampaign_BAO_TwingleApiCall $twingleApi
|
* @param \CRM_TwingleCampaign_BAO_TwingleApiCall $twingleApi
|
||||||
* @param array $params
|
* @param array $params
|
||||||
|
* @param bool $update Update project after push?
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws \CiviCRM_API3_Exception
|
* @throws \CiviCRM_API3_Exception
|
||||||
*/
|
*/
|
||||||
function _pushProjectToTwingle(TwingleProject $project,
|
function _pushProjectToTwingle(TwingleProject $project,
|
||||||
TwingleApiCall $twingleApi,
|
TwingleApiCall $twingleApi,
|
||||||
array $params): array {
|
array $params = [],
|
||||||
|
bool $update = TRUE): array {
|
||||||
|
|
||||||
// If this is a test, do not make db changes
|
// If this is a test, do not make db changes
|
||||||
if ($params['is_test']) {
|
if (isset($params['is_test']) && $params['is_test']) {
|
||||||
$response[$project->getId] =
|
$response[$project->getId()] =
|
||||||
$project->getResponse('TwingleProject ready to push to Twingle');
|
$project->getResponse('TwingleProject ready to push to Twingle');
|
||||||
return civicrm_api3_create_success(
|
return civicrm_api3_create_success(
|
||||||
$response,
|
$response,
|
||||||
|
@ -379,6 +395,7 @@ function _pushProjectToTwingle(TwingleProject $project,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update local campaign with data returning from Twingle
|
// Update local campaign with data returning from Twingle
|
||||||
|
if ($update) {
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$project->update($result);
|
$project->update($result);
|
||||||
try {
|
try {
|
||||||
|
@ -419,6 +436,17 @@ function _pushProjectToTwingle(TwingleProject $project,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$response[$project->getId()] =
|
||||||
|
$project->getResponse('TwingleProject pushed to Twingle');
|
||||||
|
return civicrm_api3_create_success(
|
||||||
|
$response,
|
||||||
|
$params,
|
||||||
|
'TwingleProject',
|
||||||
|
'Sync'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache;
|
use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache;
|
||||||
|
use CRM_TwingleCampaign_BAO_TwingleProject as TwingleProject;
|
||||||
|
use CRM_TwingleCampaign_BAO_TwingleApiCall as TwingleApiCall;
|
||||||
use CRM_TwingleCampaign_ExtensionUtil as E;
|
use CRM_TwingleCampaign_ExtensionUtil as E;
|
||||||
|
|
||||||
require_once 'twinglecampaign.civix.php';
|
require_once 'twinglecampaign.civix.php';
|
||||||
|
@ -9,6 +11,7 @@ require_once 'twinglecampaign.civix.php';
|
||||||
* Implements hook_civicrm_config().
|
* Implements hook_civicrm_config().
|
||||||
*
|
*
|
||||||
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
|
* @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config/
|
||||||
|
*
|
||||||
* @param $config
|
* @param $config
|
||||||
*/
|
*/
|
||||||
function twinglecampaign_civicrm_config(&$config) {
|
function twinglecampaign_civicrm_config(&$config) {
|
||||||
|
@ -63,15 +66,20 @@ function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) {
|
||||||
// If the db transaction is still running, add a function to it that will
|
// If the db transaction is still running, add a function to it that will
|
||||||
// be called afterwards
|
// be called afterwards
|
||||||
if (CRM_Core_Transaction::isActive()) {
|
if (CRM_Core_Transaction::isActive()) {
|
||||||
|
|
||||||
|
if (_validateAndSendInput($dao->id, $dao->campaign_type_id)) {
|
||||||
|
|
||||||
CRM_Core_Transaction::addCallback(
|
CRM_Core_Transaction::addCallback(
|
||||||
CRM_Core_Transaction::PHASE_POST_COMMIT,
|
CRM_Core_Transaction::PHASE_POST_COMMIT,
|
||||||
'twinglecampaign_postSave_campaign_callback',
|
'twinglecampaign_postSave_campaign_update_callback',
|
||||||
[$dao->id, $dao->campaign_type_id]
|
[$dao->id, $dao->campaign_type_id]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the transaction is already finished, call the function directly
|
// If the transaction is already finished, call the function directly
|
||||||
else {
|
else {
|
||||||
twinglecampaign_postSave_campaign_callback($dao->id, $dao->campaign_type_id);
|
twinglecampaign_postSave_campaign_update_callback($dao->id, $dao->campaign_type_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -89,21 +97,13 @@ function twinglecampaign_civicrm_postSave_civicrm_campaign($dao) {
|
||||||
*
|
*
|
||||||
* @throws \CiviCRM_API3_Exception
|
* @throws \CiviCRM_API3_Exception
|
||||||
*/
|
*/
|
||||||
function twinglecampaign_postSave_campaign_callback (
|
function twinglecampaign_postSave_campaign_update_callback(
|
||||||
int $campaign_id,
|
int $campaign_id,
|
||||||
int $campaign_type_id
|
int $campaign_type_id
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Get campaign type id for TwingleProject
|
$twingle_project_campaign_type_id = _get_campaign_type_id_twingle_project();
|
||||||
$twingle_project_campaign_type_id =
|
$twingle_campaign_campaign_type_id = _get_campaign_type_id_twingle_campaign();
|
||||||
ExtensionCache::getInstance()
|
|
||||||
->getCampaigns()['campaign_types']['twingle_project']['id'];
|
|
||||||
|
|
||||||
// Get campaign type id for TwingleCampaign
|
|
||||||
$twingle_campaign_campaign_type_id =
|
|
||||||
ExtensionCache::getInstance()
|
|
||||||
->getCampaigns()['campaign_types']['twingle_campaign']['id'];
|
|
||||||
|
|
||||||
|
|
||||||
// If $campaign_type_id is a TwingleProject or TwingleCampaign campaign,
|
// If $campaign_type_id is a TwingleProject or TwingleCampaign campaign,
|
||||||
// synchronize it
|
// synchronize it
|
||||||
|
@ -121,15 +121,14 @@ function twinglecampaign_postSave_campaign_callback (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['action'])) {
|
if (isset($_POST['action'])) {
|
||||||
if ($_POST['action'] == 'clone') {
|
if ($_POST['action'] == 'clone' && $entity == 'TwingleProject') {
|
||||||
unset($_POST['action']);
|
unset($_POST['action']);
|
||||||
$result = civicrm_api3($entity, 'getsingle',
|
$result = civicrm_api3('TwingleProject', 'getsingle',
|
||||||
['id' => $campaign_id]
|
['id' => $campaign_id]
|
||||||
)['values'][$campaign_id];
|
);
|
||||||
$className = 'CRM_TwingleCampaign_BAO_' . $entity;
|
|
||||||
$id = $result['id'];
|
$id = $result['id'];
|
||||||
unset($result['id']);
|
unset($result['id']);
|
||||||
$project = new $className($result, $id);
|
$project = new TwingleProject($result, $id);
|
||||||
try {
|
try {
|
||||||
$project->clone();
|
$project->clone();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
@ -137,23 +136,42 @@ function twinglecampaign_postSave_campaign_callback (
|
||||||
E::LONG_NAME .
|
E::LONG_NAME .
|
||||||
' could not clone ' . $entity . ': ' . $e->getMessage()
|
' could not clone ' . $entity . ': ' . $e->getMessage()
|
||||||
);
|
);
|
||||||
CRM_Utils_System::setUFMessage($entity . ' could not get cloned.');
|
CRM_Core_Session::setStatus(
|
||||||
|
$e->getMessage(),
|
||||||
|
E::ts("Campaign cloning failed"),
|
||||||
|
error,
|
||||||
|
[unique => TRUE]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a TwingleProject is getting saved
|
||||||
elseif ($entity == 'TwingleProject') {
|
elseif ($entity == 'TwingleProject') {
|
||||||
|
|
||||||
|
// Synchronize all child TwingleCampaign campaigns
|
||||||
try {
|
try {
|
||||||
civicrm_api3('TwingleProject', 'sync', ['id' => $campaign_id]);
|
civicrm_api3(
|
||||||
CRM_Utils_System::setUFMessage('TwingleProject was saved.');
|
'TwingleCampaign',
|
||||||
|
'sync',
|
||||||
|
['parent_id' => $campaign_id]);
|
||||||
} catch (CiviCRM_API3_Exception $e) {
|
} catch (CiviCRM_API3_Exception $e) {
|
||||||
|
CRM_Core_Session::setStatus(
|
||||||
|
$e->getMessage(),
|
||||||
|
E::ts("TwingleCampaign update failed"),
|
||||||
|
error, [unique => TRUE]
|
||||||
|
);
|
||||||
Civi::log()->error(
|
Civi::log()->error(
|
||||||
'twinglecampaign_postSave_callback ' . $e->getMessage()
|
E::SHORT_NAME .
|
||||||
|
' Update of TwingleCampaigns failed: ' . $e->getMessage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
civicrm_api3('TwingleCampaign', 'create', ['id' => $campaign_id]);
|
civicrm_api3('TwingleCampaign', 'create',
|
||||||
CRM_Utils_System::setUFMessage('TwingleCampaign was saved.');
|
['id' => $campaign_id, 'parent_id' => $_POST['parent_id']]);
|
||||||
|
CRM_Utils_System::setUFMessage(E::ts('TwingleCampaign was saved.'));
|
||||||
} catch (CiviCRM_API3_Exception $e) {
|
} catch (CiviCRM_API3_Exception $e) {
|
||||||
Civi::log()->error(
|
Civi::log()->error(
|
||||||
'twinglecampaign_postSave_callback ' . $e->getMessage()
|
'twinglecampaign_postSave_callback ' . $e->getMessage()
|
||||||
|
@ -161,18 +179,7 @@ function twinglecampaign_postSave_campaign_callback (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif ($entity == 'TwingleProject') {
|
|
||||||
// Also synchronize all child TwingleCampaign campaigns
|
|
||||||
try {
|
|
||||||
civicrm_api3('TwingleCampaign', 'sync', ['project_id' => $campaign_id]);
|
|
||||||
} catch (CiviCRM_API3_Exception $e) {
|
|
||||||
Civi::log()->error(
|
|
||||||
'twinglecampaign_postSave_callback ' . $e->getMessage()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
civicrm_api3('TwingleProject', 'sync', ['id' => $campaign_id]);
|
|
||||||
CRM_Utils_System::setUFMessage('TwingleProject was saved.');
|
|
||||||
|
|
||||||
function _get_campaign_type_id_twingle_project() {
|
function _get_campaign_type_id_twingle_project() {
|
||||||
return ExtensionCache::getInstance()
|
return ExtensionCache::getInstance()
|
||||||
|
@ -184,11 +191,177 @@ function _get_campaign_type_id_twingle_campaign() {
|
||||||
->getCampaignIds()['campaign_types']['twingle_campaign']['id'];
|
->getCampaignIds()['campaign_types']['twingle_campaign']['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
'twinglecampaign_postSave_callback ' . $e->getMessage()
|
/**
|
||||||
|
* Callback to sync a project after its creation.
|
||||||
|
* @param int $campaign_id
|
||||||
|
*/
|
||||||
|
function twinglecampaign_postSave_project_create_callback(
|
||||||
|
int $campaign_id
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
civicrm_api3(
|
||||||
|
'TwingleProject',
|
||||||
|
'sync',
|
||||||
|
['id' => $campaign_id]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
CRM_Core_Session::setStatus(
|
||||||
|
$e->getMessage(),
|
||||||
|
E::ts("TwingleProject creation failed"),
|
||||||
|
error, [unique => TRUE]
|
||||||
|
);
|
||||||
|
Civi::log()->error(
|
||||||
|
E::SHORT_NAME .
|
||||||
|
' Update of TwingleProject creation failed: ' . $e->getMessage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First validate and then sends the input of this transaction to Twinge.
|
||||||
|
* If the call to the Twingle API succeeded, this function returns TRUE;
|
||||||
|
*
|
||||||
|
* @param $id
|
||||||
|
* @param $campaign_type_id
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \CiviCRM_API3_Exception
|
||||||
|
*/
|
||||||
|
function _validateAndSendInput($id, $campaign_type_id): bool {
|
||||||
|
|
||||||
|
// Set callback for cloning
|
||||||
|
if (isset($_POST['action'])) {
|
||||||
|
CRM_Core_Transaction::addCallback(
|
||||||
|
CRM_Core_Transaction::PHASE_POST_COMMIT,
|
||||||
|
'twinglecampaign_postSave_campaign_update_callback',
|
||||||
|
[$id, $campaign_type_id]
|
||||||
|
);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($campaign_type_id == _get_campaign_type_id_twingle_project()) {
|
||||||
|
|
||||||
|
// Instantiate project
|
||||||
|
$project = new TwingleProject();
|
||||||
|
|
||||||
|
// Translate custom fields from $_POST
|
||||||
|
$customFields = [];
|
||||||
|
$customFieldsKeys = preg_grep('/^custom_/', array_keys($_POST));
|
||||||
|
foreach ($customFieldsKeys as $key) {
|
||||||
|
$customFields[preg_replace('/_-?\d*$/', '', $key)] =
|
||||||
|
$_POST[$key];
|
||||||
|
}
|
||||||
|
$project->translateCustomFields(
|
||||||
|
$customFields,
|
||||||
|
TwingleProject::OUT
|
||||||
|
);
|
||||||
|
TwingleProject::formatValues($customFields, TwingleProject::OUT);
|
||||||
|
|
||||||
|
// Update project
|
||||||
|
$project->update($customFields);
|
||||||
|
|
||||||
|
// Validate project values
|
||||||
|
$validation = $project->validate();
|
||||||
|
|
||||||
|
// If the input is valid, send it to Twingle
|
||||||
|
if ($validation['valid']) {
|
||||||
|
|
||||||
|
// Try to retrieve twingleApi from cache or create a new
|
||||||
|
$twingleApi = Civi::cache()->get('twinglecampaign_twingle_api');
|
||||||
|
if (NULL === $twingleApi) {
|
||||||
|
try {
|
||||||
|
$twingleApi =
|
||||||
|
new TwingleApiCall(Civi::settings()->get('twingle_api_key'));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
|
||||||
|
// Roll back transaction if input validation failed
|
||||||
|
CRM_Core_Transaction::rollbackIfFalse(FALSE);
|
||||||
|
|
||||||
|
CRM_Core_Session::setStatus(
|
||||||
|
$e->getMessage(),
|
||||||
|
E::ts("Could not retrieve Twingle API key"),
|
||||||
|
error,
|
||||||
|
[unique => TRUE]
|
||||||
|
);
|
||||||
|
Civi::log()->error(
|
||||||
|
E::SHORT_NAME .
|
||||||
|
' Could not retrieve Twingle API key: ' . $e->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Civi::cache('long')->set('twinglecampaign_twingle_api', $twingleApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Complement project values with values from Twingle if it has a
|
||||||
|
// project_id
|
||||||
|
if ($project->getProjectId()) {
|
||||||
|
$project_from_twingle = $twingleApi->getProject($project->getProjectId());
|
||||||
|
$project->complement($project_from_twingle);
|
||||||
|
}
|
||||||
|
// If this campaign is just about to become created, add a callback to
|
||||||
|
// sync it after the transaction has finished
|
||||||
|
else {
|
||||||
|
CRM_Core_Transaction::addCallback(
|
||||||
|
CRM_Core_Transaction::PHASE_POST_COMMIT,
|
||||||
|
'twinglecampaign_postSave_project_create_callback', [$id]
|
||||||
|
);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push project
|
||||||
|
require E::path() . '/api/v3/TwingleProject/Sync.php';
|
||||||
|
$result = _pushProjectToTwingle($project, $twingleApi, [], FALSE);
|
||||||
|
if ($result['is_error'] != 0) {
|
||||||
|
throw new \CiviCRM_API3_Exception($result['error_message']);
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
|
||||||
|
// Roll back transaction if input validation failed
|
||||||
|
CRM_Core_Transaction::rollbackIfFalse(FALSE);
|
||||||
|
|
||||||
|
// Display and log error message
|
||||||
|
CRM_Core_Session::setStatus(
|
||||||
|
$e->getMessage(),
|
||||||
|
E::ts("TwingleProject synchronization failed: %1",
|
||||||
|
[1 => $e->getMessage()]),
|
||||||
|
error,
|
||||||
|
[unique => TRUE]
|
||||||
|
);
|
||||||
|
Civi::log()->error(
|
||||||
|
E::SHORT_NAME .
|
||||||
|
' TwingleProject synchronization failed: ' . $e->getMessage()
|
||||||
|
);
|
||||||
|
// Push failed
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
// Push succeeded
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
// Display error message if validation failed
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Roll back transaction if input validation failed
|
||||||
|
CRM_Core_Transaction::rollbackIfFalse(FALSE);
|
||||||
|
|
||||||
|
// Build error message
|
||||||
|
$errorMessage = '<ul>';
|
||||||
|
foreach ($validation['messages'] as $message) {
|
||||||
|
$errorMessage = $errorMessage . '<li>' . $message . '</li>';
|
||||||
|
}
|
||||||
|
$errorMessage = $errorMessage . '</ul>';
|
||||||
|
|
||||||
|
CRM_Core_Session::setStatus(
|
||||||
|
$errorMessage,
|
||||||
|
E::ts("Input validation failed"),
|
||||||
|
error,
|
||||||
|
[unique => TRUE]
|
||||||
|
);
|
||||||
|
// Validation failed
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TwingleCampaigns always return TRUE;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue