implement TwingleCampaign

This commit is contained in:
Marc Michalsky forumZFD 2021-02-08 13:56:54 +01:00
parent cf6ed7344f
commit f3d242fce7
Signed by untrusted user who does not match committer: marc.koch
GPG key ID: 12406554CFB028B9
3 changed files with 438 additions and 25 deletions

View file

@ -1,28 +1,363 @@
<?php <?php
use CRM_TwingleCampaign_Utils_ExtensionCache as ExtensionCache;
use CRM_TwingleCampaign_ExtensionUtil as E;
class CRM_TwingleCampaign_BAO_TwingleCampaign { class CRM_TwingleCampaign_BAO_TwingleCampaign {
// IN means: heading into CiviCRM database
public const IN = 'IN';
// OUT means: coming from the CiviCRM database
public const OUT = 'OUT';
private $prefix;
private $id; private $id;
private $tw_cid; private $campaign_type_id;
private $values;
/** /**
* TwingleCampaign constructor. * ## TwingleCampaign constructor
*
* @param array|null $values
*
* @throws CiviCRM_API3_Exception
*/ */
public function __construct() { public function __construct(array $values = NULL) {
$this->prefix = 'twingle_campaign_';
$this->id = $values['id'] ?? NULL;
$this->values['campaign_type_id'] = 'twingle_campaign';
if ($this->id) {
$this->fetch();
if ($values) {
$this->update($values);
}
$this->getParentProject();
$this->createCid();
$this->createUrl();
}
elseif ($values) {
$this->update($values);
}
}
/**
* ## Create TwingleCampaign
* Create this TwingleCampaign as a campaign in CiviCRM
*
* @param bool $no_hook
*
* @throws \CiviCRM_API3_Exception
*/
public function create(bool $no_hook = FALSE) {
// Set a flag to not trigger the hook
if ($no_hook) {
$_SESSION['CiviCRM']['de.forumzfd.twinglecampaign']['no_hook'] = TRUE;
}
$values = $this->values;
$this->translateCustomFields($values, self::IN);
$result = civicrm_api3('Campaign', 'create', $values);
if ($result['is_error'] != 1) {
$this->id = $result['id'];
$this->values = $result['values'];
}
}
/**
* ## Fetch TwingleCampaign
* Populate this instance with values from an existing TwingleCampaign.
*
* @throws CiviCRM_API3_Exception
*/
private function fetch() {
$this->values = civicrm_api3('Campaign', 'getsingle',
['id' => $this->id]);
}
/**
* ## Get Parent Project
* Determines the id of the parent TwingleProject. If there is no parent
* TwingleProject, an error message is shown on UI and the campaign gets
* deleted.
*
* @throws \CiviCRM_API3_Exception
*/
private function getParentProject(): void {
// Get campaign type id for TwingleProject
$twingle_project_campaign_type_id =
ExtensionCache::getInstance()
->getCampaigns()['campaign_types']['twingle_project']['id'];
// Determine the parent project id by looping through the campaign tree
// until the parent campaign type is a TwingleProject
$parent_id = $this->values['parent_id'];
$parent_campaign_type_id = NULL;
while ($parent_id && $parent_campaign_type_id != $twingle_project_campaign_type_id) {
// Get parent campaign
$parent_campaign = civicrm_api3('Campaign', 'getsingle',
['id' => $parent_id]);
if ($parent_campaign['is_error'] != 1) {
$parent_campaign_type_id = $parent_campaign['campaign_type_id'];
if ($parent_campaign['parent_id']) {
$parent_id = $parent_campaign['parent_id'];
}
else {
break;
}
}
else {
throw new CiviCRM_API3_Exception($parent_campaign['error_message']);
}
}
// Set parent_project_id and retrieve parent_project_url
if ($parent_campaign_type_id == $twingle_project_campaign_type_id) {
$this->values['parent_project_id'] = $parent_id;
// Get custom field name for twingle_project_page field
$cf_page = ExtensionCache::getInstance()
->getCustomFieldMapping('twingle_project_page');
// Extract twingle_project_page url from parent_campaign
if ($parent_campaign[$cf_page]) {
$this->values['parent_project_url'] = $parent_campaign[$cf_page];
}
// If twingle_project_widget value is missing, try a synchronization
else {
$parent_campaign = civicrm_api3('TwingleProject', 'sync',
['id' => $parent_id]);
// Now try again to extract the twingle_project_widget url
if ($parent_campaign[$cf_url]) {
$this->values['parent_project_url'] = $parent_campaign[$cf_url];
}
// If twingle_project_widget value is still missing, show an alert on
// UI, log an error and delete this TwingleCampaign
else {
CRM_Core_Session::setStatus(
ts("Could not determine parent TwingleProject URL. This URL is
needed to create the TwingleEvent URL. Please check the logs."),
ts('Parent project URL missing'),
'alert'
);
Civi::log()->error(
E::LONG_NAME .
' could not determine parent TwingleProject URL.',
$this->getResponse()
);
$this->delete();
}
}
// If this TwingleCampaign has no parent TwingleProject above it in the
// campaign tree
}
else {
CRM_Core_Session::setStatus(
ts("TwingleCampaigns can only get created as a child of a
TwingleProject in the campaign tree."),
ts('No parent TwingleProject found'),
'alert'
);
$this->delete();
}
}
/**
* ## Create URL
* Create a URL by adding a tw_cid
*/
private function createUrl() {
$this->values['url'] =
$this->values['parent_project_url'] . '?tw_cid=' . $this->values['cid'];
}
/**
*
*/
private function createCid() {
$this->values['cid'] = md5($this->id . '_' . $this->values['name']);
}
/**
*
*/
private function validateCid() {
} }
public function create() {
/**
*
*/
private function decodeCid() {
} }
public function exists() {
/**
* ## Translate field names and custom field names
*
* Constants for **$direction**:<br>
* **Campaign::IN** Translate field name to custom field name <br>
* **Campaign::OUT** Translate from custom field name to field name
*
* @param array $values
* array of keys to translate
*
* @param string $direction
* const: Campaign::OUT or Campaign::OUT
*/
public function translateCustomFields(array &$values, string $direction) {
// Translate field name to custom field name
if ($direction == self::IN) {
foreach (ExtensionCache::getInstance()
->getCustomFieldMapping() as $field => $custom) {
if (array_key_exists(
str_replace(
$this->prefix,
'',
$field
),
$values)
) {
$values[$custom] = $values[str_replace(
$this->prefix,
'',
$field
)];
unset($values[str_replace(
$this->prefix,
'',
$field
)]
);
}
}
}
// Translate from custom field name to field name
elseif ($direction == self::OUT) {
foreach (ExtensionCache::getInstance()
->getCustomFieldMapping() as $field => $custom) {
if (array_key_exists(
$custom,
$values
)
) {
$values[str_replace(
$this->prefix,
'',
$field
)] = $values[$custom];
unset($values[$custom]);
}
}
}
} }
/**
* ## Delete TwingleCampaign
* Deletes this TwingleCampaign from CiviCRM
*/
private function delete() {
if ($this->id) {
try {
civicrm_api3('Campaign', 'delete', ['id' => $this->id]);
} catch (CiviCRM_API3_Exception $e) {
Civi::log()->error(
E::LONG_NAME .
' could delete TwingleCampaign: ' .
$e->getMessage(),
$this->getResponse()
);
}
}
}
/**
* ## Get a response
* Get a response that describes the status of this TwingleCampaign instance.
* Returns an array that contains **title**, **id**, **parent_project_id**
* (if available) and **status** (if provided)
*
* @param string|null $status
* status of the TwingleCampaign you want to give back along with the response
*
* @return array
*/
public function getResponse(string $status = NULL): array {
$response = [
'title' => $this->values['title'],
'id' => (int) $this->id,
];
if ($status) {
$response['status'] = $status;
}
if ($this->values['parent_project_id']) {
$response['parent_project_id'] = (int) $this->values['parent_project_id'];
}
return $response;
}
/**
* ## Update values
* Updates all values in **$this->values** array.
*
* @param array $values
* values that should get updated
*/
private function update(array $values) {
$filter = ExtensionCache::getInstance()->getTemplates()['TwingleCampaign'];
foreach ($values as $key => $value) {
if (in_array($key, $filter)) {
$this->values[$key] = $values[$key];
}
}
}
/**
* ## Clone this TwingleProject
*
* This method removes the id from this instance and in the next step it
* creates the clone as a new TwingleCampaign with the same values to
* Twingle.
*
* @throws \CiviCRM_API3_Exception
*/
public function clone() {
// TODO: implement cloning
}
} }

View file

@ -130,6 +130,19 @@
"is_view": 0, "is_view": 0,
"weight": 5 "weight": 5
}, },
"twingle_project_page": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Page",
"name": "twingle_project_page",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 0,
"weight": 1
},
"twingle_project_widget": { "twingle_project_widget": {
"custom_group_id": "Twingle_Project_Embed_Codes", "custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Widget", "label": "Twingle Project Widget",
@ -399,6 +412,32 @@
"is_active": 1, "is_active": 1,
"is_view": 1, "is_view": 1,
"weight": 15 "weight": 15
},
"twingle_campaign_parent_project_id": {
"custom_group_id": "Twingle_Campaign_Information",
"label": "Parent TwingleProject ID",
"name": "twingle_campaign_parent_project_id",
"is_required": 0,
"is_searchable": 1,
"data_type": "String",
"html_type": "Text",
"text_length": 16,
"is_active": 1,
"is_view": 1,
"weight": 1
},
"twingle_campaign_url": {
"custom_group_id": "Twingle_Campaign_Information",
"label": "Twingle Campaign URL",
"name": "twingle_campaign_url",
"is_required": 0,
"is_searchable": 0,
"data_type": "Memo",
"html_type": "TextArea",
"text_length": 600,
"is_active": 1,
"is_view": 1,
"weight": 2
} }
} }
} }

View file

@ -1,4 +1,6 @@
<?php <?php
use CRM_TwingleCampaign_BAO_TwingleCampaign as TwingleCampaign;
use CRM_TwingleCampaign_ExtensionUtil as E; use CRM_TwingleCampaign_ExtensionUtil as E;
/** /**
@ -9,37 +11,74 @@ use CRM_TwingleCampaign_ExtensionUtil as E;
* *
* @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/ * @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/
*/ */
function _civicrm_api3_twingle_campaign_Create_spec(&$spec) { function _civicrm_api3_twingle_campaign_Create_spec(array &$spec) {
$spec['magicword']['api.required'] = 1; $spec['id'] = [
'name' => 'id',
'title' => E::ts('Twingle Project ID'),
'type' => CRM_Utils_Type::T_INT,
'api.required' => 0,
'description' => E::ts('The Twingle Project ID'),
];
$spec['name'] = [
'name' => 'name',
'title' => E::ts('Twingle Campaign Name'),
'type' => CRM_Utils_Type::T_STRING,
'api.required' => 0,
'description' => E::ts('Name of the Twingle Project'),
];
$spec['title'] = [
'name' => 'title',
'title' => E::ts('Twingle Campaign Title'),
'type' => CRM_Utils_Type::T_STRING,
'api.required' => 1,
'description' => E::ts('Title of the Twingle Campaign'),
];
$spec['parent_id'] = [
'name' => 'parent_id',
'title' => E::ts('Parent Campaign'),
'type' => CRM_Utils_Type::T_INT,
'api.required' => 1,
'description' => E::ts('Optional parent id for this Campaign'),
];
} }
/** /**
* TwingleCampaign.Create API * # TwingleCampaign.Create API
* *
* @param array $params * @param array $params
* *
* @return array * @return array
* API result descriptor * API result descriptor
* *
* @throws CiviCRM_API3_Exception
* @see civicrm_api3_create_success * @see civicrm_api3_create_success
*
* @throws API_Exception
*/ */
function civicrm_api3_twingle_campaign_Create($params) { function civicrm_api3_twingle_campaign_Create(array $params): array {
if (array_key_exists('magicword', $params) && $params['magicword'] == 'sesame') {
$returnValues = array(
// OK, return several data rows
12 => ['id' => 12, 'name' => 'Twelve'],
34 => ['id' => 34, 'name' => 'Thirty four'],
56 => ['id' => 56, 'name' => 'Fifty six'],
);
// ALTERNATIVE: $returnValues = []; // OK, success
// ALTERNATIVE: $returnValues = ["Some value"]; // OK, return a single value
// Spec: civicrm_api3_create_success($values = 1, $params = [], $entity = NULL, $action = NULL) // instantiate TwingleCampaign
return civicrm_api3_create_success($returnValues, $params, 'TwingleCampaign', 'Create'); $campaign = new TwingleCampaign($params);
}
else { // Try to create the TwingleCampaign
throw new API_Exception(/*error_message*/ 'Everyone knows that the magicword is "sesame"', /*error_code*/ 'magicword_incorrect'); try {
$campaign->create();
return civicrm_api3_create_success(
$campaign->getResponse('TwingleCampaign created'),
$params,
'TwingleCampaign',
'Create'
);
} catch(Exception $e){
Civi::log()->error(
E::LONG_NAME .
' could not create TwingleCampaign: ' .
$e->getMessage(),
$campaign->getResponse()
);
return civicrm_api3_create_error(
'Could not create TwingleCampaign: ' . $e->getMessage(),
$campaign->getResponse()
);
} }
} }