From d60aa3825ba02633d47eddacac8fc8d742c2db19 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 10:00:32 +0200 Subject: [PATCH 1/9] [#1] added config page --- CRM/Contactsource/Form/Settings.php | 101 +++++++++++++++++ contactsource.civix.php | 105 ++++++++++-------- templates/CRM/Contactsource/Form/Settings.tpl | 46 ++++++++ xml/Menu/contactsource.xml | 11 ++ 4 files changed, 219 insertions(+), 44 deletions(-) create mode 100644 CRM/Contactsource/Form/Settings.php create mode 100644 templates/CRM/Contactsource/Form/Settings.tpl create mode 100644 xml/Menu/contactsource.xml diff --git a/CRM/Contactsource/Form/Settings.php b/CRM/Contactsource/Form/Settings.php new file mode 100644 index 0000000..2d3802e --- /dev/null +++ b/CRM/Contactsource/Form/Settings.php @@ -0,0 +1,101 @@ +add( + 'select', + 'contact_source_sync', + E::ts("Copy to contact's source field"), + [ + '' => E::ts("don't"), + 'first_campaign' => E::ts("First contact (campaign)"), + 'first_subject' => E::ts("First contact (subject)"), + 'all_campaign' => E::ts("All contacts (campaign)"), + 'all_subject' => E::ts("All contacts (subject)"), + ], + FALSE + ); + $this->add( + 'checkbox', + 'contact_source_sync_now', + E::ts("Copy data now!") + ); + + // autofill source subject + $this->add( + 'select', + 'contact_source_subject', + E::ts("Fill Contact Source"), + [ + '' => E::ts("don't"), + 'campaign_title' => E::ts("with campaign title") + ], + FALSE + ); + $this->add( + 'checkbox', + 'contact_source_subject_now', + E::ts("Fill Contact Source now!") + ); + + // add form elements + $this->addButtons([ + [ + 'type' => 'submit', + 'name' => E::ts('Apply'), + 'isDefault' => TRUE, + ], + ]); + + // set current values + $this->setDefaults([ + 'contact_source_sync' => Civi::settings()->get('contact_source_sync'), + 'contact_source_subject' => Civi::settings()->get('contact_source_subject'), + ]); + + parent::buildQuickForm(); + } + + public function postProcess() + { + // first: store values + $values = $this->exportValues(); + Civi::settings()->set('contact_source_sync', CRM_Utils_Array::value('contact_source_sync', $values, '')); + Civi::settings()->set('contact_source_subject', CRM_Utils_Array::value('contact_source_subject', $values, '')); + + // then: run any updates + if (!empty($values['contact_source_subject_now'])) { + // TODO: run subject fill query + CRM_Core_Session::setStatus(E::ts("%1 contact source activity subjects filled.")); + } + if (!empty($values['contact_source_sync_now'])) { + // TODO: run subject fill query + CRM_Core_Session::setStatus(E::ts("%1 contact source fields updated.")); + } + parent::postProcess(); + } + +} diff --git a/contactsource.civix.php b/contactsource.civix.php index 70b3311..3102ca8 100644 --- a/contactsource.civix.php +++ b/contactsource.civix.php @@ -24,9 +24,9 @@ class CRM_Contactsource_ExtensionUtil { * Translated text. * @see ts */ - public static function ts($text, $params = array()) { + public static function ts($text, $params = []) { if (!array_key_exists('domain', $params)) { - $params['domain'] = array(self::LONG_NAME, NULL); + $params['domain'] = [self::LONG_NAME, NULL]; } return ts($text, $params); } @@ -82,7 +82,7 @@ public static function findClass($suffix) { /** * (Delegated) Implements hook_civicrm_config(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_config */ function _contactsource_civix_civicrm_config(&$config = NULL) { static $configured = FALSE; @@ -100,7 +100,7 @@ function _contactsource_civix_civicrm_config(&$config = NULL) { array_unshift($template->template_dir, $extDir); } else { - $template->template_dir = array($extDir, $template->template_dir); + $template->template_dir = [$extDir, $template->template_dir]; } $include_path = $extRoot . PATH_SEPARATOR . get_include_path(); @@ -112,7 +112,7 @@ function _contactsource_civix_civicrm_config(&$config = NULL) { * * @param $files array(string) * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_xmlMenu */ function _contactsource_civix_civicrm_xmlMenu(&$files) { foreach (_contactsource_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) { @@ -123,7 +123,7 @@ function _contactsource_civix_civicrm_xmlMenu(&$files) { /** * Implements hook_civicrm_install(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install */ function _contactsource_civix_civicrm_install() { _contactsource_civix_civicrm_config(); @@ -135,12 +135,12 @@ function _contactsource_civix_civicrm_install() { /** * Implements hook_civicrm_postInstall(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_postInstall */ function _contactsource_civix_civicrm_postInstall() { _contactsource_civix_civicrm_config(); if ($upgrader = _contactsource_civix_upgrader()) { - if (is_callable(array($upgrader, 'onPostInstall'))) { + if (is_callable([$upgrader, 'onPostInstall'])) { $upgrader->onPostInstall(); } } @@ -149,7 +149,7 @@ function _contactsource_civix_civicrm_postInstall() { /** * Implements hook_civicrm_uninstall(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_uninstall */ function _contactsource_civix_civicrm_uninstall() { _contactsource_civix_civicrm_config(); @@ -161,12 +161,12 @@ function _contactsource_civix_civicrm_uninstall() { /** * (Delegated) Implements hook_civicrm_enable(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable */ function _contactsource_civix_civicrm_enable() { _contactsource_civix_civicrm_config(); if ($upgrader = _contactsource_civix_upgrader()) { - if (is_callable(array($upgrader, 'onEnable'))) { + if (is_callable([$upgrader, 'onEnable'])) { $upgrader->onEnable(); } } @@ -175,13 +175,13 @@ function _contactsource_civix_civicrm_enable() { /** * (Delegated) Implements hook_civicrm_disable(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_disable * @return mixed */ function _contactsource_civix_civicrm_disable() { _contactsource_civix_civicrm_config(); if ($upgrader = _contactsource_civix_upgrader()) { - if (is_callable(array($upgrader, 'onDisable'))) { + if (is_callable([$upgrader, 'onDisable'])) { $upgrader->onDisable(); } } @@ -196,7 +196,7 @@ function _contactsource_civix_civicrm_disable() { * @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending) * for 'enqueue', returns void * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_upgrade */ function _contactsource_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) { if ($upgrader = _contactsource_civix_upgrader()) { @@ -217,22 +217,23 @@ function _contactsource_civix_upgrader() { } /** - * Search directory tree for files which match a glob pattern + * Search directory tree for files which match a glob pattern. * * Note: Dot-directories (like "..", ".git", or ".svn") will be ignored. * Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles() * - * @param $dir string, base dir - * @param $pattern string, glob pattern, eg "*.txt" + * @param string $dir base dir + * @param string $pattern , glob pattern, eg "*.txt" + * * @return array(string) */ function _contactsource_civix_find_files($dir, $pattern) { - if (is_callable(array('CRM_Utils_File', 'findFiles'))) { + if (is_callable(['CRM_Utils_File', 'findFiles'])) { return CRM_Utils_File::findFiles($dir, $pattern); } - $todos = array($dir); - $result = array(); + $todos = [$dir]; + $result = []; while (!empty($todos)) { $subdir = array_shift($todos); foreach (_contactsource_civix_glob("$subdir/$pattern") as $match) { @@ -259,10 +260,11 @@ function _contactsource_civix_find_files($dir, $pattern) { * * Find any *.mgd.php files, merge their content, and return. * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_managed */ function _contactsource_civix_civicrm_managed(&$entities) { $mgdFiles = _contactsource_civix_find_files(__DIR__, '*.mgd.php'); + sort($mgdFiles); foreach ($mgdFiles as $file) { $es = include $file; foreach ($es as $e) { @@ -284,7 +286,7 @@ function _contactsource_civix_civicrm_managed(&$entities) { * * Note: This hook only runs in CiviCRM 4.4+. * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_caseTypes */ function _contactsource_civix_civicrm_caseTypes(&$caseTypes) { if (!is_dir(__DIR__ . '/xml/case')) { @@ -295,14 +297,13 @@ function _contactsource_civix_civicrm_caseTypes(&$caseTypes) { $name = preg_replace('/\.xml$/', '', basename($file)); if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) { $errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name)); - CRM_Core_Error::fatal($errorMessage); - // throw new CRM_Core_Exception($errorMessage); + throw new CRM_Core_Exception($errorMessage); } - $caseTypes[$name] = array( + $caseTypes[$name] = [ 'module' => E::LONG_NAME, 'name' => $name, 'file' => $file, - ); + ]; } } @@ -313,7 +314,7 @@ function _contactsource_civix_civicrm_caseTypes(&$caseTypes) { * * Note: This hook only runs in CiviCRM 4.5+. * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_angularModules */ function _contactsource_civix_civicrm_angularModules(&$angularModules) { if (!is_dir(__DIR__ . '/ang')) { @@ -331,6 +332,25 @@ function _contactsource_civix_civicrm_angularModules(&$angularModules) { } } +/** + * (Delegated) Implements hook_civicrm_themes(). + * + * Find any and return any files matching "*.theme.php" + */ +function _contactsource_civix_civicrm_themes(&$themes) { + $files = _contactsource_civix_glob(__DIR__ . '/*.theme.php'); + foreach ($files as $file) { + $themeMeta = include $file; + if (empty($themeMeta['name'])) { + $themeMeta['name'] = preg_replace(':\.theme\.php$:', '', basename($file)); + } + if (empty($themeMeta['ext'])) { + $themeMeta['ext'] = E::LONG_NAME; + } + $themes[$themeMeta['name']] = $themeMeta; + } +} + /** * Glob wrapper which is guaranteed to return an array. * @@ -341,11 +361,12 @@ function _contactsource_civix_civicrm_angularModules(&$angularModules) { * * @link http://php.net/glob * @param string $pattern + * * @return array, possibly empty */ function _contactsource_civix_glob($pattern) { $result = glob($pattern); - return is_array($result) ? $result : array(); + return is_array($result) ? $result : []; } /** @@ -356,16 +377,18 @@ function _contactsource_civix_glob($pattern) { * 'Mailing', or 'Administer/System Settings' * @param array $item - the item to insert (parent/child attributes will be * filled for you) + * + * @return bool */ function _contactsource_civix_insert_navigation_menu(&$menu, $path, $item) { // If we are done going down the path, insert menu if (empty($path)) { - $menu[] = array( - 'attributes' => array_merge(array( + $menu[] = [ + 'attributes' => array_merge([ 'label' => CRM_Utils_Array::value('name', $item), 'active' => 1, - ), $item), - ); + ], $item), + ]; return TRUE; } else { @@ -376,9 +399,9 @@ function _contactsource_civix_insert_navigation_menu(&$menu, $path, $item) { foreach ($menu as $key => &$entry) { if ($entry['attributes']['name'] == $first) { if (!isset($entry['child'])) { - $entry['child'] = array(); + $entry['child'] = []; } - $found = _contactsource_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item, $key); + $found = _contactsource_civix_insert_navigation_menu($entry['child'], implode('/', $path), $item); } } return $found; @@ -389,7 +412,7 @@ function _contactsource_civix_insert_navigation_menu(&$menu, $path, $item) { * (Delegated) Implements hook_civicrm_navigationMenu(). */ function _contactsource_civix_navigationMenu(&$nodes) { - if (!is_callable(array('CRM_Core_BAO_Navigation', 'fixNavigationMenu'))) { + if (!is_callable(['CRM_Core_BAO_Navigation', 'fixNavigationMenu'])) { _contactsource_civix_fixNavigationMenu($nodes); } } @@ -431,17 +454,11 @@ function _contactsource_civix_fixNavigationMenuItems(&$nodes, &$maxNavID, $paren /** * (Delegated) Implements hook_civicrm_alterSettingsFolders(). * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_alterSettingsFolders + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_alterSettingsFolders */ function _contactsource_civix_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) { - static $configured = FALSE; - if ($configured) { - return; - } - $configured = TRUE; - $settingsDir = __DIR__ . DIRECTORY_SEPARATOR . 'settings'; - if (is_dir($settingsDir) && !in_array($settingsDir, $metaDataFolders)) { + if (!in_array($settingsDir, $metaDataFolders) && is_dir($settingsDir)) { $metaDataFolders[] = $settingsDir; } } @@ -451,7 +468,7 @@ function _contactsource_civix_civicrm_alterSettingsFolders(&$metaDataFolders = N * * Find any *.entityType.php files, merge their content, and return. * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_entityTypes + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_entityTypes */ function _contactsource_civix_civicrm_entityTypes(&$entityTypes) { diff --git a/templates/CRM/Contactsource/Form/Settings.tpl b/templates/CRM/Contactsource/Form/Settings.tpl new file mode 100644 index 0000000..c64e9bc --- /dev/null +++ b/templates/CRM/Contactsource/Form/Settings.tpl @@ -0,0 +1,46 @@ +{*-------------------------------------------------------+ +| SYSTOPIA Contact Source Extension | +| Copyright (C) 2020 SYSTOPIA | +| Author: B. Endres (endres@systopia.de) | +| http://www.systopia.de/ | ++--------------------------------------------------------+ +| This program is released as free software under the | +| Affero GPL license. You can redistribute it and/or | +| modify it under the terms of this license which you | +| can read by viewing the included agpl.txt or online | +| at www.gnu.org/licenses/agpl.html. Removal of this | +| copyright header is strictly prohibited without | +| written permission from the original author(s). | ++--------------------------------------------------------*} + +{crmScope extensionKey='de.systopia.contactsource'} +

{ts}Fill Contact's Source Field{/ts}

+
+
{$form.contact_source_sync.label}
+
{$form.contact_source_sync.html}
+
+
+ +
+
{$form.contact_source_sync_now.label}
+
{$form.contact_source_sync_now.html}
+
+
+ +

{ts}Fill Contact Source Activity Subject{/ts}

+
+
{$form.contact_source_subject.label}
+
{$form.contact_source_subject.html}
+
+
+ +
+
{$form.contact_source_subject_now.label}
+
{$form.contact_source_subject_now.html}
+
+
+ +
+ {include file="CRM/common/formButtons.tpl" location="bottom"} +
+{/crmScope} \ No newline at end of file diff --git a/xml/Menu/contactsource.xml b/xml/Menu/contactsource.xml new file mode 100644 index 0000000..dec8f15 --- /dev/null +++ b/xml/Menu/contactsource.xml @@ -0,0 +1,11 @@ + + + + civicrm/admin/contactsource + CRM_Contactsource_Form_Settings + Contact Source Settings + administer CiviCRM + Communications + admin/import_export_map.png + + \ No newline at end of file From cc546fcb5f355ce240937cfb4cf089e6f3bb532d Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 10:01:25 +0200 Subject: [PATCH 2/9] PSR-12 Code formatting --- CRM/Contactsource/Contactsource.php | 76 +++++++++++++++-------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index d8519cb..d9be653 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -20,14 +20,16 @@ /** * Contact Source Functions */ -class CRM_Contactsource_Contactsource { +class CRM_Contactsource_Contactsource +{ /** * Inject contact source (by activity) into summary view - * + * * @param $page CRM_Core_Page */ - public static function injectInPage($page) { + public static function injectInPage($page) + { $pageName = $page->getVar('_name'); // only if contact summary if ($pageName == 'CRM_Contact_Page_View_Summary') { @@ -36,38 +38,9 @@ public static function injectInPage($page) { if ($contact_source_string) { $page->assign('contact_source_string', $contact_source_string); CRM_Core_Region::instance('page-body')->add(array( - 'template' => 'CRM/Contactsource/Contactsource.tpl')); - } - } - } - - /** - * Return a chronologically ordered list of the contact's sources - * - * @param $contact_id int contact ID - * @return array list of activities - */ - public static function getContactSources($contact_id) { - if (empty($contact_id)) { - return []; - } - - // look up activities - static $sources_by_contact = []; - if (!isset($sources_by_contact[$contact_id])) { - $sources_by_contact[$contact_id] = []; - $activities = civicrm_api3('Activity', 'get', [ - 'target_contact_id' => $contact_id, - 'activity_type_id' => CRM_Contactsource_Configuration::getActivityTypeID(), - 'option' => ['limit' => 0, - 'sort' => 'activity_date_time asc'], - 'return' => 'datetime,subject,campaign', - ]); - foreach ($activities['values'] as $activity) { - $sources_by_contact[$contact_id][] = $activity; + 'template' => 'CRM/Contactsource/Contactsource.tpl')); } } - return $sources_by_contact[$contact_id]; } /** @@ -77,10 +50,11 @@ public static function getContactSources($contact_id) { * @param $max_len * @return string */ - public static function getContactSourceString($contact_id, $max_len) { + public static function getContactSourceString($contact_id, $max_len) + { $activities = self::getContactSources($contact_id); $contact_sources = ''; - $sources_joined = 0; + $sources_joined = 0; foreach ($activities as $activity) { if ($sources_joined >= $max_len) { break; @@ -91,7 +65,7 @@ public static function getContactSourceString($contact_id, $max_len) { $contact_sources .= ', '; } $contact_sources .= $activity['subject']; - $sources_joined += 1; + $sources_joined += 1; } } @@ -100,4 +74,34 @@ public static function getContactSourceString($contact_id, $max_len) { } return $contact_sources; } + + /** + * Return a chronologically ordered list of the contact's sources + * + * @param $contact_id int contact ID + * @return array list of activities + */ + public static function getContactSources($contact_id) + { + if (empty($contact_id)) { + return []; + } + + // look up activities + static $sources_by_contact = []; + if (!isset($sources_by_contact[$contact_id])) { + $sources_by_contact[$contact_id] = []; + $activities = civicrm_api3('Activity', 'get', [ + 'target_contact_id' => $contact_id, + 'activity_type_id' => CRM_Contactsource_Configuration::getActivityTypeID(), + 'option' => ['limit' => 0, + 'sort' => 'activity_date_time asc'], + 'return' => 'datetime,subject,campaign', + ]); + foreach ($activities['values'] as $activity) { + $sources_by_contact[$contact_id][] = $activity; + } + } + return $sources_by_contact[$contact_id]; + } } From f5ab1b0d781950fe86b67d2dc60168db8f316002 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 10:26:16 +0200 Subject: [PATCH 3/9] [#4] implemeted activity source fill (bulk) --- CRM/Contactsource/Configuration.php | 127 +++++++++++------- CRM/Contactsource/Contactsource.php | 191 +++++++++++++++++----------- CRM/Contactsource/Form/Settings.php | 136 ++++++++++---------- 3 files changed, 271 insertions(+), 183 deletions(-) diff --git a/CRM/Contactsource/Configuration.php b/CRM/Contactsource/Configuration.php index 90e7d15..47d04c9 100644 --- a/CRM/Contactsource/Configuration.php +++ b/CRM/Contactsource/Configuration.php @@ -15,56 +15,97 @@ +--------------------------------------------------------*/ -use CRM_Contactsource_ExtensionUtil as E; - /** * Collection of upgrade steps. */ -class CRM_Contactsource_Configuration { +class CRM_Contactsource_Configuration +{ + + const CONTACT_SOURCE_ACTIVITY_TYPE = 'contact_source'; + const CONTACT_SOURCE_FIELD_LENGTH = 255; - const CONTACT_SOURCE_ACTIVITY_TYPE = 'contact_source'; + protected static $activity_type_id = NULL; - protected static $activity_type_id = NULL; + /** + * Get the extensions "First Contact" activity type ID + */ + public static function getActivityTypeID() + { + if (self::$activity_type_id === NULL) { + $activity_types = civicrm_api3('OptionValue', 'get', [ + 'option_group_id' => 'activity_type', + 'name' => self::CONTACT_SOURCE_ACTIVITY_TYPE + ]); + switch ($activity_types['count']) { + case 0: + // doesn't exit yet => create + civicrm_api3('OptionValue', 'create', [ + 'option_group_id' => 'activity_type', + 'name' => self::CONTACT_SOURCE_ACTIVITY_TYPE, + 'label' => E::ts("First Contact"), + 'is_active' => 1, + 'is_reserved' => 1, + 'filter' => 0, + 'icon' => 'fa-user-plus']); + return self::getActivityTypeID(); - /** - * Get the extensions "First Contact" activity type ID - */ - public static function getActivityTypeID() { - if (self::$activity_type_id === NULL) { - $activity_types = civicrm_api3('OptionValue', 'get', [ - 'option_group_id' => 'activity_type', - 'name' => self::CONTACT_SOURCE_ACTIVITY_TYPE - ]); - switch ($activity_types['count']) { - case 0: - // doesn't exit yet => create - civicrm_api3('OptionValue', 'create', [ - 'option_group_id' => 'activity_type', - 'name' => self::CONTACT_SOURCE_ACTIVITY_TYPE, - 'label' => E::ts("First Contact"), - 'is_active' => 1, - 'is_reserved' => 1, - 'filter' => 0, - 'icon' => 'fa-user-plus']); - return self::getActivityTypeID(); + case 1: + // found one + $activity_type = reset($activity_types['values']); + if (empty($activity_type['is_active'])) { + // still needs to be activated + civicrm_api3('OptionValue', 'create', [ + 'id' => $activity_type['id'], + 'is_active' => 1]); + } + self::$activity_type_id = $activity_type['value']; + break; - case 1: - // found one - $activity_type = reset($activity_types['values']); - if (empty($activity_type['is_active'])) { - // still needs to be activated - civicrm_api3('OptionValue', 'create', [ - 'id' => $activity_type['id'], - 'is_active' => 1]); - } - self::$activity_type_id = $activity_type['value']; - break; + default: + // found multiple ones + throw new Exception("Multiple activity types of name '" . self::CONTACT_SOURCE_ACTIVITY_TYPE . "' found. Please fix activity_type option group!"); + } + } + return self::$activity_type_id; + } + + /** + * Get the default contact source activity subject. + * + * @return string + * '': don't fill at all + * 'campaign_title': fill with campaign title + * + */ + public static function getDefaultActivitySubject() + { + $value = Civi::settings()->get('contact_source_subject'); + if (empty($value)) { + return ''; + } else { + return $value; + } + } - default: - // found multiple ones - throw new Exception("Multiple activity types of name '" . self::CONTACT_SOURCE_ACTIVITY_TYPE . "' found. Please fix activity_type option group!"); - } + /** + * Get the mode to sync the contact source activities to the + * contact's source field + * + * @return string + * '' => "disabled" + * 'first_campaign' => "First contact (campaign)" + * 'first_subject' => "First contact (subject)" + * 'all_campaign' => "All contacts (campaign)" + * 'all_subject' => "All contacts (subject)" + * + */ + public static function getContactSourceSync() + { + $value = Civi::settings()->get('contact_source_sync'); + if (empty($value)) { + return ''; + } else { + return $value; + } } - return self::$activity_type_id; - } } diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index d9be653..5268863 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -1,7 +1,7 @@ getVar('_name'); - // only if contact summary - if ($pageName == 'CRM_Contact_Page_View_Summary') { - $contact_id = $page->getVar('_contactId'); - $contact_source_string = self::getContactSourceString($contact_id, 2); - if ($contact_source_string) { - $page->assign('contact_source_string', $contact_source_string); - CRM_Core_Region::instance('page-body')->add(array( - 'template' => 'CRM/Contactsource/Contactsource.tpl')); - } + /** + * Inject contact source (by activity) into summary view + * + * @param $page CRM_Core_Page + */ + public static function injectInPage($page) + { + $pageName = $page->getVar('_name'); + // only if contact summary + if ($pageName == 'CRM_Contact_Page_View_Summary') { + $contact_id = $page->getVar('_contactId'); + $contact_source_string = self::getContactSourceString($contact_id, 2); + if ($contact_source_string) { + $page->assign('contact_source_string', $contact_source_string); + CRM_Core_Region::instance('page-body')->add(array( + 'template' => 'CRM/Contactsource/Contactsource.tpl')); + } + } } - } - /** - * Get a string summing up the list of sources - * - * @param $contact_id - * @param $max_len - * @return string - */ - public static function getContactSourceString($contact_id, $max_len) - { - $activities = self::getContactSources($contact_id); - $contact_sources = ''; - $sources_joined = 0; - foreach ($activities as $activity) { - if ($sources_joined >= $max_len) { - break; - } + /** + * Get a string summing up the list of sources + * + * @param integer $contact_id + * contact ID + * @param integer $max_len + * maximum number of sources + * @return string + * calculated string + */ + public static function getContactSourceString($contact_id, $max_len) + { + $activities = self::getContactSources($contact_id); + $contact_sources = ''; + $sources_joined = 0; + foreach ($activities as $activity) { + if ($sources_joined >= $max_len) { + break; + } - if (!empty($activity['subject'])) { - if ($contact_sources) { - $contact_sources .= ', '; + if (!empty($activity['subject'])) { + if ($contact_sources) { + $contact_sources .= ', '; + } + $contact_sources .= $activity['subject']; + $sources_joined += 1; + } } - $contact_sources .= $activity['subject']; - $sources_joined += 1; - } - } - if ($max_len < count($activities)) { - $contact_sources .= ', ...'; + if ($max_len < count($activities)) { + $contact_sources .= ', ...'; + } + return $contact_sources; } - return $contact_sources; - } - /** - * Return a chronologically ordered list of the contact's sources - * - * @param $contact_id int contact ID - * @return array list of activities - */ - public static function getContactSources($contact_id) - { - if (empty($contact_id)) { - return []; + /** + * Return a chronologically ordered list of the contact's sources + * + * @param integer $contact_id + * contact ID + * + * @return array + * list of activities + */ + public static function getContactSources($contact_id) + { + if (empty($contact_id)) { + return []; + } + + // look up activities + static $sources_by_contact = []; + if (!isset($sources_by_contact[$contact_id])) { + $sources_by_contact[$contact_id] = []; + $activities = civicrm_api3('Activity', 'get', [ + 'target_contact_id' => $contact_id, + 'activity_type_id' => CRM_Contactsource_Configuration::getActivityTypeID(), + 'option' => ['limit' => 0, + 'sort' => 'activity_date_time asc'], + 'return' => 'datetime,subject,campaign', + ]); + foreach ($activities['values'] as $activity) { + $sources_by_contact[$contact_id][] = $activity; + } + } + return $sources_by_contact[$contact_id]; } - // look up activities - static $sources_by_contact = []; - if (!isset($sources_by_contact[$contact_id])) { - $sources_by_contact[$contact_id] = []; - $activities = civicrm_api3('Activity', 'get', [ - 'target_contact_id' => $contact_id, - 'activity_type_id' => CRM_Contactsource_Configuration::getActivityTypeID(), - 'option' => ['limit' => 0, - 'sort' => 'activity_date_time asc'], - 'return' => 'datetime,subject,campaign', - ]); - foreach ($activities['values'] as $activity) { - $sources_by_contact[$contact_id][] = $activity; - } + + /** + * Will update (i.e. fill) all activity subjects according to the settings + * + * @return integer + * count of updated contacts + */ + public static function updateAllContactSourceActivitySubjects() + { + $fill_mode = CRM_Contactsource_Configuration::getDefaultActivitySubject(); + if (empty($fill_mode)) { + return 0; + } + + $activity_type_id = CRM_Contactsource_Configuration::getActivityTypeID(); + if ($fill_mode == 'campaign_title') { + // find out how many are empty + $eligible_fields = CRM_Core_DAO::singleValueQuery(" + SELECT COUNT(*) + FROM civicrm_activity first_contact_activity + WHERE activity_type_id = {$activity_type_id} + AND (subject IS NULL OR subject = '') + AND campaign_id IS NOT NULL + "); + // fill the subject + CRM_Core_DAO::executeQuery(" + UPDATE civicrm_activity first_contact_activity + LEFT JOIN civicrm_campaign first_contact_campaign ON first_contact_campaign.id = first_contact_activity.campaign_id + SET first_contact_activity.subject = first_contact_campaign.title + WHERE activity_type_id = {$activity_type_id} + AND (subject IS NULL OR subject = '') + AND campaign_id IS NOT NULL + "); + return $eligible_fields; + + } else { + throw new Exception("Subject fill mode '{$fill_mode}' undefined!"); + } } - return $sources_by_contact[$contact_id]; - } + } diff --git a/CRM/Contactsource/Form/Settings.php b/CRM/Contactsource/Form/Settings.php index 2d3802e..fc1ae97 100644 --- a/CRM/Contactsource/Form/Settings.php +++ b/CRM/Contactsource/Form/Settings.php @@ -22,80 +22,80 @@ class CRM_Contactsource_Form_Settings extends CRM_Core_Form { - public function buildQuickForm() - { - // synchronise contact source - $this->add( - 'select', - 'contact_source_sync', - E::ts("Copy to contact's source field"), - [ - '' => E::ts("don't"), - 'first_campaign' => E::ts("First contact (campaign)"), - 'first_subject' => E::ts("First contact (subject)"), - 'all_campaign' => E::ts("All contacts (campaign)"), - 'all_subject' => E::ts("All contacts (subject)"), - ], - FALSE - ); - $this->add( - 'checkbox', - 'contact_source_sync_now', - E::ts("Copy data now!") - ); + public function buildQuickForm() + { + // synchronise contact source + $this->add( + 'select', + 'contact_source_sync', + E::ts("Copy to contact's source field"), + [ + '' => E::ts("disabled"), + 'first_campaign' => E::ts("First contact (campaign)"), + 'first_subject' => E::ts("First contact (subject)"), + 'all_campaign' => E::ts("All contacts (campaign)"), + 'all_subject' => E::ts("All contacts (subject)"), + ], + FALSE + ); + $this->add( + 'checkbox', + 'contact_source_sync_now', + E::ts("Copy data now!") + ); - // autofill source subject - $this->add( - 'select', - 'contact_source_subject', - E::ts("Fill Contact Source"), - [ - '' => E::ts("don't"), - 'campaign_title' => E::ts("with campaign title") - ], - FALSE - ); - $this->add( - 'checkbox', - 'contact_source_subject_now', - E::ts("Fill Contact Source now!") - ); + // autofill source subject + $this->add( + 'select', + 'contact_source_subject', + E::ts("Fill Contact Source"), + [ + '' => E::ts("don't"), + 'campaign_title' => E::ts("with campaign title") + ], + FALSE + ); + $this->add( + 'checkbox', + 'contact_source_subject_now', + E::ts("Fill Contact Source now!") + ); - // add form elements - $this->addButtons([ - [ - 'type' => 'submit', - 'name' => E::ts('Apply'), - 'isDefault' => TRUE, - ], - ]); + // add form elements + $this->addButtons([ + [ + 'type' => 'submit', + 'name' => E::ts('Apply'), + 'isDefault' => TRUE, + ], + ]); - // set current values - $this->setDefaults([ - 'contact_source_sync' => Civi::settings()->get('contact_source_sync'), - 'contact_source_subject' => Civi::settings()->get('contact_source_subject'), - ]); + // set current values + $this->setDefaults([ + 'contact_source_sync' => Civi::settings()->get('contact_source_sync'), + 'contact_source_subject' => CRM_Contactsource_Configuration::getDefaultActivitySubject(), + ]); - parent::buildQuickForm(); - } + parent::buildQuickForm(); + } - public function postProcess() - { - // first: store values - $values = $this->exportValues(); - Civi::settings()->set('contact_source_sync', CRM_Utils_Array::value('contact_source_sync', $values, '')); - Civi::settings()->set('contact_source_subject', CRM_Utils_Array::value('contact_source_subject', $values, '')); + public function postProcess() + { + // first: store values + $values = $this->exportValues(); + Civi::settings()->set('contact_source_sync', CRM_Utils_Array::value('contact_source_sync', $values, '')); + Civi::settings()->set('contact_source_subject', CRM_Utils_Array::value('contact_source_subject', $values, '')); - // then: run any updates - if (!empty($values['contact_source_subject_now'])) { - // TODO: run subject fill query - CRM_Core_Session::setStatus(E::ts("%1 contact source activity subjects filled.")); - } - if (!empty($values['contact_source_sync_now'])) { - // TODO: run subject fill query - CRM_Core_Session::setStatus(E::ts("%1 contact source fields updated.")); + // then: run any updates + if (!empty($values['contact_source_subject_now'])) { + $actvitites_updated = CRM_Contactsource_Contactsource::updateAllContactSourceActivitySubjects(); + CRM_Core_Session::setStatus(E::ts("%1 contact source activity subjects filled.", [1 => $actvitites_updated])); + } + if (!empty($values['contact_source_sync_now'])) { + // TODO: run subject fill query + CRM_Core_Session::setStatus(E::ts("%1 contact source fields updated.")); + } + parent::postProcess(); } - parent::postProcess(); - } } From f36757b09d1cbdd7125bf94e02fb1fafc7bde725 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 10:39:25 +0200 Subject: [PATCH 4/9] [#4] implemeted activity source fill (hook) --- CRM/Contactsource/Contactsource.php | 20 ++++++++++++++++++++ contactsource.php | 19 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index 5268863..b90b80d 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -112,6 +112,26 @@ public static function getContactSources($contact_id) } + /** + * Calculate the contact source activity subject based on the settings + * + * @return string + * suggested activity source + */ + public static function getContactSourceActivitySubject($activity_data) { + $fill_mode = CRM_Contactsource_Configuration::getDefaultActivitySubject(); + if ($fill_mode == 'campaign_title' + && !empty($activity_data['campaign_id'])) { + return civicrm_api3('Campaign', 'getvalue', [ + 'id' => $activity_data['campaign_id'], + 'return' => 'title', + ]); + } + + // fallback: nothing + return ''; + } + /** * Will update (i.e. fill) all activity subjects according to the settings * diff --git a/contactsource.php b/contactsource.php index 3f3899a..3ae41b3 100644 --- a/contactsource.php +++ b/contactsource.php @@ -149,8 +149,6 @@ function contactsource_civicrm_entityTypes(&$entityTypes) { _contactsource_civix_civicrm_entityTypes($entityTypes); } -// --- Functions below this ship commented out. Uncomment as required. --- - /** * Implements hook_civicrm_buildForm(). * @@ -186,6 +184,23 @@ function contactsource_civicrm_pageRun(&$page) { CRM_Contactsource_Contactsource::injectInPage($page); } +/** + * Implements hook_civicrm_pageRun + * + * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_pageRun + */ +function contactsource_civicrm_pre($op, $objectName, $id, &$params) { + if ($objectName == 'Activity' && $op == 'create') { + $contact_source_activity_type = CRM_Contactsource_Configuration::getActivityTypeID(); + if ($params['activity_type_id'] == $contact_source_activity_type) { + // this is a contact source activity type + if (empty($params['subject'])) { + $params['subject'] = CRM_Contactsource_Contactsource::getContactSourceActivitySubject($params); + } + } + } +} + /** * Implements hook_civicrm_navigationMenu(). * From 6e816d3d9cf46a9d26d5b83a24a4a018d3ab3981 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 13:53:58 +0200 Subject: [PATCH 5/9] [#3] implemeted bulk update --- CRM/Contactsource/Configuration.php | 2 +- CRM/Contactsource/Contactsource.php | 159 ++++++++++++++++++++++++++++ CRM/Contactsource/Form/Settings.php | 4 +- 3 files changed, 162 insertions(+), 3 deletions(-) diff --git a/CRM/Contactsource/Configuration.php b/CRM/Contactsource/Configuration.php index 47d04c9..c34c9d5 100644 --- a/CRM/Contactsource/Configuration.php +++ b/CRM/Contactsource/Configuration.php @@ -99,7 +99,7 @@ public static function getDefaultActivitySubject() * 'all_subject' => "All contacts (subject)" * */ - public static function getContactSourceSync() + public static function getContactSourceSyncMode() { $value = Civi::settings()->get('contact_source_sync'); if (empty($value)) { diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index b90b80d..2600ae0 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -171,4 +171,163 @@ public static function updateAllContactSourceActivitySubjects() } } + /** + * Update contact source fields according to configured mode + * + * @param array $contact_ids + * contact IDs to update. If empty, ALL contacts are updated + * + * @return integer + * count of updated contacts + */ + public static function updateContactSourceField($contact_ids = null) + { + $change_count = 0; + $mode = CRM_Contactsource_Configuration::getContactSourceSyncMode(); + if (empty($mode)) { + return 0; + } + + // get activity type ID + $activity_type_id = CRM_Contactsource_Configuration::getActivityTypeID(); + + // get contact clause + $CONTACT_CLAUSE = 'TRUE'; + if (!empty($contact_ids) && is_array($contact_ids)) { + $clean_contact_ids = []; + foreach ($contact_ids as $contact_id) { + $clean_contact_ids[] = (int) $contact_id; + } + $CONTACT_CLAUSE = 'IN (' . implode(',', $clean_contact_ids) . ')'; + } + + if ($mode == 'first_campaign' || $mode == 'first_subject') { + // SINGLE VALUE MODE + // first step: find out which is the first contribution + $first_contact_table = CRM_Utils_SQL_TempTable::build(); + $first_contact_table->createWithQuery(" + SELECT + contact.id AS contact_id, + contact.source AS current_source, + contact.source AS new_source, + MIN(first_contact.activity_date_time) AS first_contact + FROM civicrm_contact contact + LEFT JOIN civicrm_activity_contact ac + ON contact.id = ac.contact_id + AND ac.record_type_id = 3 + LEFT JOIN civicrm_activity first_contact + ON first_contact.id = ac.activity_id + AND first_contact.activity_type_id = {$activity_type_id} + WHERE {$CONTACT_CLAUSE} + AND first_contact.id IS NOT NULL + GROUP BY contact.id; + "); + $first_contact_table_name = $first_contact_table->getName(); + CRM_Core_DAO::executeQuery("ALTER TABLE {$first_contact_table_name} ADD INDEX contact_id(contact_id)"); + + // next step: calculate new subject + $subject_term = ($mode == 'first_campaign') ? "campaign.title" : "activity.subject"; + CRM_Core_DAO::executeQuery(" + UPDATE {$first_contact_table_name} first_contact + LEFT JOIN civicrm_activity_contact ac + ON ac.contact_id = first_contact.contact_id + AND ac.record_type_id = 3 + LEFT JOIN civicrm_activity activity + ON activity.id = ac.activity_id + AND activity.activity_type_id = {$activity_type_id} + AND activity.activity_date_time = first_contact.first_contact + LEFT JOIN civicrm_campaign campaign + ON campaign.id = activity.campaign_id + SET first_contact.new_source = COALESCE({$subject_term}) + "); + + // calculate count + $change_count = CRM_Core_DAO::singleValueQuery(" + SELECT COUNT(*) + FROM {$first_contact_table_name} + WHERE (current_source IS NULL AND new_source IS NOT NULL) + OR current_source <> new_source + "); + + // finally: update contact + CRM_Core_DAO::executeQuery(" + UPDATE civicrm_contact contact + LEFT JOIN {$first_contact_table_name} first_contact + ON first_contact.contact_id = contact.id + SET contact.source = first_contact.new_source + WHERE (contact.source IS NULL AND first_contact.new_source IS NOT NULL) + OR contact.source <> first_contact.new_source + "); + + // cleanup + $first_contact_table->drop(); + + + } elseif ($mode == 'all_campaign' || $mode == 'all_subject') { + // AGGREGATED VALUE MODE + // first step: find out which is the first contribution + $first_contact_table = CRM_Utils_SQL_TempTable::build(); + $first_contact_table->createWithQuery(" + SELECT + contact.id AS contact_id, + first_contact.id AS activity_id + FROM civicrm_contact contact + LEFT JOIN civicrm_activity_contact ac + ON contact.id = ac.contact_id + AND ac.record_type_id = 3 + LEFT JOIN civicrm_activity first_contact + ON first_contact.id = ac.activity_id + AND first_contact.activity_type_id = {$activity_type_id} + WHERE {$CONTACT_CLAUSE} + AND first_contact.id IS NOT NULL + ORDER BY first_contact.activity_date_time ASC + "); + $first_contact_table_name = $first_contact_table->getName(); + CRM_Core_DAO::executeQuery("ALTER TABLE {$first_contact_table_name} ADD INDEX contact_id(contact_id)"); + + // seconds step: calculate old and new subject + $subject_term = ($mode == 'all_campaign') ? "campaign.title" : "activity.subject"; + $subject_update_table = CRM_Utils_SQL_TempTable::build(); + $subject_update_table->createWithQuery(" + SELECT + first_contact.contact_id AS contact_id, + contact.source AS current_source, + SUBSTRING(GROUP_CONCAT(DISTINCT({$subject_term}) SEPARATOR ', '), 1, 255) AS new_source + FROM {$first_contact_table_name} first_contact + LEFT JOIN civicrm_activity activity + ON activity.id = first_contact.activity_id + LEFT JOIN civicrm_campaign campaign + ON campaign.id = activity.campaign_id + LEFT JOIN civicrm_contact contact + ON contact.id = first_contact.contact_id + GROUP BY contact.id + "); + + // calculate count + $subject_update_table_name = $subject_update_table->getName(); + $change_count = CRM_Core_DAO::singleValueQuery(" + SELECT COUNT(*) + FROM {$subject_update_table_name} + WHERE (current_source IS NULL AND new_source IS NOT NULL) + OR current_source <> new_source + "); + + + // finally: update contact + CRM_Core_DAO::executeQuery(" + UPDATE civicrm_contact contact + LEFT JOIN {$subject_update_table_name} first_contact + ON first_contact.contact_id = contact.id + SET contact.source = first_contact.new_source + WHERE (contact.source IS NULL AND first_contact.new_source IS NOT NULL) + OR contact.source <> first_contact.new_source + "); + + // cleanup + $first_contact_table->drop(); + $subject_update_table->drop(); + } + + return $change_count; + } } diff --git a/CRM/Contactsource/Form/Settings.php b/CRM/Contactsource/Form/Settings.php index fc1ae97..37a880b 100644 --- a/CRM/Contactsource/Form/Settings.php +++ b/CRM/Contactsource/Form/Settings.php @@ -92,8 +92,8 @@ public function postProcess() CRM_Core_Session::setStatus(E::ts("%1 contact source activity subjects filled.", [1 => $actvitites_updated])); } if (!empty($values['contact_source_sync_now'])) { - // TODO: run subject fill query - CRM_Core_Session::setStatus(E::ts("%1 contact source fields updated.")); + $actvitites_updated = CRM_Contactsource_Contactsource::updateContactSourceField(); + CRM_Core_Session::setStatus(E::ts("%1 contact source fields updated.", [1 => $actvitites_updated])); } parent::postProcess(); } From 28ec4f81037c957e58e7135735fe485fe88ca572 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 13:59:25 +0200 Subject: [PATCH 6/9] [#3] added option to enable/disable source injection --- CRM/Contactsource/Configuration.php | 17 ++++++++++++++++ CRM/Contactsource/Contactsource.php | 20 ++++++++++--------- CRM/Contactsource/Form/Settings.php | 7 +++++++ templates/CRM/Contactsource/Form/Settings.tpl | 8 +++++++- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/CRM/Contactsource/Configuration.php b/CRM/Contactsource/Configuration.php index c34c9d5..e1d7445 100644 --- a/CRM/Contactsource/Configuration.php +++ b/CRM/Contactsource/Configuration.php @@ -108,4 +108,21 @@ public static function getContactSourceSyncMode() return $value; } } + + /** + * Get the mode to sync the contact source activities to the + * contact's source field + * + * @return string + * '' => "disabled" + * 'first_campaign' => "First contact (campaign)" + * 'first_subject' => "First contact (subject)" + * 'all_campaign' => "All contacts (campaign)" + * 'all_subject' => "All contacts (subject)" + * + */ + public static function sourceInjectionEnabled() + { + return !empty(Civi::settings()->get('contact_source_inject')); + } } diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index 2600ae0..4d733f3 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -30,15 +30,17 @@ class CRM_Contactsource_Contactsource */ public static function injectInPage($page) { - $pageName = $page->getVar('_name'); - // only if contact summary - if ($pageName == 'CRM_Contact_Page_View_Summary') { - $contact_id = $page->getVar('_contactId'); - $contact_source_string = self::getContactSourceString($contact_id, 2); - if ($contact_source_string) { - $page->assign('contact_source_string', $contact_source_string); - CRM_Core_Region::instance('page-body')->add(array( - 'template' => 'CRM/Contactsource/Contactsource.tpl')); + if (CRM_Contactsource_Configuration::sourceInjectionEnabled()) { + $pageName = $page->getVar('_name'); + // only if contact summary + if ($pageName == 'CRM_Contact_Page_View_Summary') { + $contact_id = $page->getVar('_contactId'); + $contact_source_string = self::getContactSourceString($contact_id, 2); + if ($contact_source_string) { + $page->assign('contact_source_string', $contact_source_string); + CRM_Core_Region::instance('page-body')->add(array( + 'template' => 'CRM/Contactsource/Contactsource.tpl')); + } } } } diff --git a/CRM/Contactsource/Form/Settings.php b/CRM/Contactsource/Form/Settings.php index 37a880b..5421839 100644 --- a/CRM/Contactsource/Form/Settings.php +++ b/CRM/Contactsource/Form/Settings.php @@ -25,6 +25,11 @@ class CRM_Contactsource_Form_Settings extends CRM_Core_Form public function buildQuickForm() { // synchronise contact source + $this->add( + 'checkbox', + 'contact_source_inject', + E::ts("Inject additional source field") + ); $this->add( 'select', 'contact_source_sync', @@ -72,6 +77,7 @@ public function buildQuickForm() // set current values $this->setDefaults([ + 'contact_source_inject' => CRM_Contactsource_Configuration::sourceInjectionEnabled(), 'contact_source_sync' => Civi::settings()->get('contact_source_sync'), 'contact_source_subject' => CRM_Contactsource_Configuration::getDefaultActivitySubject(), ]); @@ -83,6 +89,7 @@ public function postProcess() { // first: store values $values = $this->exportValues(); + Civi::settings()->set('contact_source_inject', CRM_Utils_Array::value('contact_source_inject', $values, 0)); Civi::settings()->set('contact_source_sync', CRM_Utils_Array::value('contact_source_sync', $values, '')); Civi::settings()->set('contact_source_subject', CRM_Utils_Array::value('contact_source_subject', $values, '')); diff --git a/templates/CRM/Contactsource/Form/Settings.tpl b/templates/CRM/Contactsource/Form/Settings.tpl index c64e9bc..cad8f11 100644 --- a/templates/CRM/Contactsource/Form/Settings.tpl +++ b/templates/CRM/Contactsource/Form/Settings.tpl @@ -15,7 +15,13 @@ {crmScope extensionKey='de.systopia.contactsource'}

{ts}Fill Contact's Source Field{/ts}

-
+
+
{$form.contact_source_inject.label}
+
{$form.contact_source_inject.html}
+
+
+ +
{$form.contact_source_sync.label}
{$form.contact_source_sync.html}
From d8d7f5ee6f016af5809c0ac04528421ff15b687b Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 14:10:23 +0200 Subject: [PATCH 7/9] [#3] added option to enable/disable form injection --- CRM/Contactsource/ActivityCreation.php | 3 +-- CRM/Contactsource/Configuration.php | 21 +++++++++---------- CRM/Contactsource/Form/Settings.php | 19 ++++++++++++----- templates/CRM/Contactsource/Form/Settings.tpl | 20 +++++++++++------- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/CRM/Contactsource/ActivityCreation.php b/CRM/Contactsource/ActivityCreation.php index a977544..a727f96 100644 --- a/CRM/Contactsource/ActivityCreation.php +++ b/CRM/Contactsource/ActivityCreation.php @@ -32,8 +32,7 @@ public static function shouldInject($form) { return false; } - // TODO: setting to turn it off? - return true; + return CRM_Contactsource_Configuration::formInjectionEnabled(); } diff --git a/CRM/Contactsource/Configuration.php b/CRM/Contactsource/Configuration.php index e1d7445..c9058b8 100644 --- a/CRM/Contactsource/Configuration.php +++ b/CRM/Contactsource/Configuration.php @@ -110,19 +110,18 @@ public static function getContactSourceSyncMode() } /** - * Get the mode to sync the contact source activities to the - * contact's source field - * - * @return string - * '' => "disabled" - * 'first_campaign' => "First contact (campaign)" - * 'first_subject' => "First contact (subject)" - * 'all_campaign' => "All contacts (campaign)" - * 'all_subject' => "All contacts (subject)" - * + * Is the injection of the artificial source field in the contact summary activated? */ public static function sourceInjectionEnabled() { - return !empty(Civi::settings()->get('contact_source_inject')); + return !empty(Civi::settings()->get('contact_source_inject_field')); + } + + /** + * Should the contact source be entered in the contact create form + */ + public static function formInjectionEnabled() + { + return !empty(Civi::settings()->get('contact_source_inject_form')); } } diff --git a/CRM/Contactsource/Form/Settings.php b/CRM/Contactsource/Form/Settings.php index 5421839..1452278 100644 --- a/CRM/Contactsource/Form/Settings.php +++ b/CRM/Contactsource/Form/Settings.php @@ -24,12 +24,19 @@ class CRM_Contactsource_Form_Settings extends CRM_Core_Form public function buildQuickForm() { - // synchronise contact source + // general settings + $this->add( + 'checkbox', + 'contact_source_inject_field', + E::ts("Inject artificial source field") + ); $this->add( 'checkbox', - 'contact_source_inject', - E::ts("Inject additional source field") + 'contact_source_inject_form', + E::ts("Add to contact create form") ); + + // synchronise contact source $this->add( 'select', 'contact_source_sync', @@ -77,7 +84,8 @@ public function buildQuickForm() // set current values $this->setDefaults([ - 'contact_source_inject' => CRM_Contactsource_Configuration::sourceInjectionEnabled(), + 'contact_source_inject_field' => CRM_Contactsource_Configuration::sourceInjectionEnabled(), + 'contact_source_inject_form' => CRM_Contactsource_Configuration::formInjectionEnabled(), 'contact_source_sync' => Civi::settings()->get('contact_source_sync'), 'contact_source_subject' => CRM_Contactsource_Configuration::getDefaultActivitySubject(), ]); @@ -89,7 +97,8 @@ public function postProcess() { // first: store values $values = $this->exportValues(); - Civi::settings()->set('contact_source_inject', CRM_Utils_Array::value('contact_source_inject', $values, 0)); + Civi::settings()->set('contact_source_inject_field', CRM_Utils_Array::value('contact_source_inject_field', $values, 0)); + Civi::settings()->set('contact_source_inject_form', CRM_Utils_Array::value('contact_source_inject_form', $values, 0)); Civi::settings()->set('contact_source_sync', CRM_Utils_Array::value('contact_source_sync', $values, '')); Civi::settings()->set('contact_source_subject', CRM_Utils_Array::value('contact_source_subject', $values, '')); diff --git a/templates/CRM/Contactsource/Form/Settings.tpl b/templates/CRM/Contactsource/Form/Settings.tpl index cad8f11..ef7c3ba 100644 --- a/templates/CRM/Contactsource/Form/Settings.tpl +++ b/templates/CRM/Contactsource/Form/Settings.tpl @@ -14,14 +14,20 @@ +--------------------------------------------------------*} {crmScope extensionKey='de.systopia.contactsource'} -

{ts}Fill Contact's Source Field{/ts}

-
-
{$form.contact_source_inject.label}
-
{$form.contact_source_inject.html}
-
-
+

{ts}General Settings{/ts}

+
+
{$form.contact_source_inject_form.label}
+
{$form.contact_source_inject_form.html}
+
+
+
+
{$form.contact_source_inject_field.label}
+
{$form.contact_source_inject_field.html}
+
+
-
+

{ts}Fill Contact's Source Field{/ts}

+
{$form.contact_source_sync.label}
{$form.contact_source_sync.html}
From 177f30e88bf46a65e4c0454ffcc9979868fcdd1e Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 14:25:50 +0200 Subject: [PATCH 8/9] [#4] implemeted activity source update (hook) --- CRM/Contactsource/Contactsource.php | 2 +- contactsource.php | 49 ++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/CRM/Contactsource/Contactsource.php b/CRM/Contactsource/Contactsource.php index 4d733f3..b795acd 100644 --- a/CRM/Contactsource/Contactsource.php +++ b/CRM/Contactsource/Contactsource.php @@ -200,7 +200,7 @@ public static function updateContactSourceField($contact_ids = null) foreach ($contact_ids as $contact_id) { $clean_contact_ids[] = (int) $contact_id; } - $CONTACT_CLAUSE = 'IN (' . implode(',', $clean_contact_ids) . ')'; + $CONTACT_CLAUSE = 'contact.id IN (' . implode(',', $clean_contact_ids) . ')'; } if ($mode == 'first_campaign' || $mode == 'first_subject') { diff --git a/contactsource.php b/contactsource.php index 3ae41b3..10617ac 100644 --- a/contactsource.php +++ b/contactsource.php @@ -202,18 +202,37 @@ function contactsource_civicrm_pre($op, $objectName, $id, &$params) { } /** - * Implements hook_civicrm_navigationMenu(). - * - * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_navigationMenu - * -function contactsource_civicrm_navigationMenu(&$menu) { - _contactsource_civix_insert_navigation_menu($menu, 'Mailings', array( - 'label' => E::ts('New subliminal message'), - 'name' => 'mailing_subliminal_message', - 'url' => 'civicrm/mailing/subliminal', - 'permission' => 'access CiviMail', - 'operator' => 'OR', - 'separator' => 0, - )); - _contactsource_civix_navigationMenu($menu); -} // */ + * Implements hook_civicrm_pageRun + * + * @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_pageRun + */ +function contactsource_civicrm_post($op, $objectName, $objectId, &$objectRef) { + if ($objectName == 'Activity' && ($op == 'edit' || $op == 'create')) { + $contact_source_activity_type = CRM_Contactsource_Configuration::getActivityTypeID(); + if (isset($objectRef->activity_type_id)) { + $activity_type_id = $objectRef->activity_type_id; + } else { + $activity_type_id = civicrm_api3('Activity', 'getvalue', [ + 'id' => $objectId, + 'return' => 'activity_type_id']); + } + if ($activity_type_id == $contact_source_activity_type) { + // maybe we need to update the contact's source field: + if (CRM_Contactsource_Configuration::getContactSourceSyncMode()) { + // get contacts + $contact_ids = CRM_Core_DAO::singleValueQuery(" + SELECT GROUP_CONCAT(contact_id) + FROM civicrm_activity_contact + WHERE activity_id = {$objectId} + AND record_type_id = 3"); + if ($contact_ids) { + CRM_Contactsource_Contactsource::updateContactSourceField(explode(',', $contact_ids)); + } + } + + if (empty($params['subject'])) { + $params['subject'] = CRM_Contactsource_Contactsource::getContactSourceActivitySubject($params); + } + } + } +} From c3bcdb5f5d9f69a69adc1df8521c32a9647aabd3 Mon Sep 17 00:00:00 2001 From: "B. Endres" Date: Tue, 23 Jun 2020 19:02:13 +0200 Subject: [PATCH 9/9] [#4] settings layout --- templates/CRM/Contactsource/Form/Settings.tpl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/CRM/Contactsource/Form/Settings.tpl b/templates/CRM/Contactsource/Form/Settings.tpl index ef7c3ba..749078d 100644 --- a/templates/CRM/Contactsource/Form/Settings.tpl +++ b/templates/CRM/Contactsource/Form/Settings.tpl @@ -15,6 +15,7 @@ {crmScope extensionKey='de.systopia.contactsource'}

{ts}General Settings{/ts}

+
{$form.contact_source_inject_form.label}
{$form.contact_source_inject_form.html}
@@ -27,6 +28,7 @@

{ts}Fill Contact's Source Field{/ts}

+
{$form.contact_source_sync.label}
{$form.contact_source_sync.html}
@@ -40,6 +42,7 @@

{ts}Fill Contact Source Activity Subject{/ts}

+
{$form.contact_source_subject.label}
{$form.contact_source_subject.html}