diff --git a/CRM/TwingleCampaign/BAO/TwingleCampaign.php b/CRM/TwingleCampaign/BAO/TwingleCampaign.php
index d8373ce..b227cbb 100644
--- a/CRM/TwingleCampaign/BAO/TwingleCampaign.php
+++ b/CRM/TwingleCampaign/BAO/TwingleCampaign.php
@@ -1,28 +1,363 @@
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**:
+ * **Campaign::IN** Translate field name to custom field name
+ * **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
+ }
+
}
\ No newline at end of file
diff --git a/CRM/TwingleCampaign/resources/campaigns.json b/CRM/TwingleCampaign/resources/campaigns.json
index 329261d..a38863c 100644
--- a/CRM/TwingleCampaign/resources/campaigns.json
+++ b/CRM/TwingleCampaign/resources/campaigns.json
@@ -130,6 +130,19 @@
"is_view": 0,
"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": {
"custom_group_id": "Twingle_Project_Embed_Codes",
"label": "Twingle Project Widget",
@@ -399,6 +412,32 @@
"is_active": 1,
"is_view": 1,
"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
}
}
}
diff --git a/api/v3/TwingleCampaign/Create.php b/api/v3/TwingleCampaign/Create.php
index f276bdf..c1aa084 100644
--- a/api/v3/TwingleCampaign/Create.php
+++ b/api/v3/TwingleCampaign/Create.php
@@ -1,4 +1,6 @@
'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
*
* @return array
* API result descriptor
*
+ * @throws CiviCRM_API3_Exception
* @see civicrm_api3_create_success
- *
- * @throws API_Exception
*/
-function civicrm_api3_twingle_campaign_Create($params) {
- 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
+function civicrm_api3_twingle_campaign_Create(array $params): array {
- // Spec: civicrm_api3_create_success($values = 1, $params = [], $entity = NULL, $action = NULL)
- return civicrm_api3_create_success($returnValues, $params, 'TwingleCampaign', 'Create');
- }
- else {
- throw new API_Exception(/*error_message*/ 'Everyone knows that the magicword is "sesame"', /*error_code*/ 'magicword_incorrect');
+ // instantiate TwingleCampaign
+ $campaign = new TwingleCampaign($params);
+
+ // Try to create the TwingleCampaign
+ 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()
+ );
}
+
}