Created
June 8, 2016 09:15
-
-
Save davidknoll/8ad934d8736459c98e445f91576c719d to your computer and use it in GitHub Desktop.
Bulk creation of Cases from Activities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
/** | |
* Convert press release activities to CiviCase | |
* | |
* @author David Knoll <david@futurefirst.org.uk> | |
*/ | |
// Bootstrap Drupal | |
const DRUPAL_ROOT = '/var/www/html/prod/drupal/'; | |
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; | |
require_once DRUPAL_ROOT . 'includes/bootstrap.inc'; | |
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); | |
// Bootstrap Civi | |
require_once DRUPAL_ROOT . 'sites/all/modules/civicrm/civicrm.config.php'; | |
require_once 'CRM/Core/Config.php'; | |
$config = CRM_Core_Config::singleton(); | |
// Log in a user | |
global $user; | |
$user = user_load(1); | |
user_login_finalize(); | |
// Body | |
if ($argc == 2 && is_numeric($argv[1])) { | |
// Do one conversion and print the result | |
$case = do_conversion($argv[1]); | |
print_r($case); | |
} | |
elseif ($argc == 2 && $argv[1] == '--all') { | |
// Convert all known 'Press Release Published' activities | |
$total_success = 0; | |
$total_failed = 0; | |
while (true) { | |
// Process one batch of 25 | |
$old_acts = civicrm_api3('Activity', 'get', array('activity_type_id' => 107, 'return' => 'id')); | |
$success = 0; | |
foreach ($old_acts['values'] as $oav) { | |
try { | |
do_conversion($oav['id']); | |
$success++; | |
$total_success++; | |
} | |
catch (Exception $e) { | |
echo "\nException converting activity {$oav['id']}: " . $e->getMessage() . "\n"; | |
$total_fail++; | |
} | |
} | |
echo '.'; | |
if (!$success) { | |
echo "\nSuccess: {$total_success} Failed: {$total_failed}\n"; | |
break; | |
} | |
} | |
} | |
elseif ($argc == 4 && $argv[1] == '--sent' && is_numeric($argv[2]) && is_numeric($argv[3])) { | |
move_sent_activity($argv[2], $argv[3]); | |
} | |
else { | |
usage(basename($argv[0])); | |
} | |
exit(0); | |
/** | |
* Print usage information and exit | |
*/ | |
function usage($name) { | |
echo <<<EOF | |
Usage: $name activity-id (convert one Published into a case) | |
$name --all (convert all Published into cases) | |
$name --sent activity-id case-id (move one Sent to an existing case) | |
EOF; | |
exit(1); | |
} | |
/** | |
* Convert an old 'Press Release Published' activity to a 'Press Release' case | |
* containing a 'Press Release: Published and AO informed' activity | |
* | |
* @param int $activity_id Old activity ID | |
* @return array New case details | |
*/ | |
function do_conversion($activity_id) { | |
$activity = get_activity($activity_id); | |
if ($activity['activity_type_id'] != 107) { | |
throw new Exception('Not a Press Release Published activity'); | |
} | |
$case_id = create_case_for($activity); | |
move_activity_to($activity, $case_id); | |
return civicrm_api3('Case', 'getsingle', array('id' => $case_id)); | |
} | |
/** | |
* Get a whole activity | |
* | |
* @param int $aid Activity ID | |
* @return array Activity details including contacts and custom fields | |
*/ | |
function get_activity($aid) { | |
// Retrieve activity, its contacts, and its custom data | |
$activity = civicrm_api3('Activity', 'getsingle', array('id' => $aid)); | |
$contacts = civicrm_api3('ActivityContact', 'get', array('activity_id' => $aid)); | |
$custom = civicrm_api3('CustomValue', 'get', array('entity_id' => $aid, 'entity_table' => 'civicrm_activity')); | |
$activity['assignee_contact_id'] = array(); | |
$activity['target_contact_id'] = array(); | |
// Arrange contact IDs | |
foreach ($contacts['values'] as $cac) { | |
switch ($cac['record_type_id']) { | |
case 1: // Assignee | |
$activity['assignee_contact_id'][] = $cac['contact_id']; | |
break; | |
case 2: // Source (can only have one) | |
$activity['source_contact_id'] = $cac['contact_id']; | |
break; | |
case 3: // Target | |
$activity['target_contact_id'][] = $cac['contact_id']; | |
break; | |
} | |
} | |
// Arrange custom data | |
foreach ($custom['values'] as $cv) { | |
// As the array contains an entry for entity_table without an ID | |
if ($cv['id']) { | |
// This won't do all records of multiple-record custom groups, | |
// but you can't have those on activities anyway | |
$activity['custom_' . $cv['id']] = $cv['latest']; | |
} | |
} | |
return $activity; | |
} | |
/** | |
* Create a case with no non-system activities, and core fields filled from supplied activity data | |
* | |
* @param array $activity Old activity details | |
* @return int New case ID | |
*/ | |
function create_case_for($activity) { | |
// Create a case, retrieve it again to get fuller details | |
$case_params = array( | |
'case_type_id' => 1, // Press Release | |
'subject' => $activity['subject'] ?: 'Case converted from activity ' . $activity['id'], | |
'start_date' => CRM_Utils_Date::customFormat($activity['activity_date_time'], '%Y%m%d'), | |
'end_date' => CRM_Utils_Date::customFormat($activity['activity_date_time'], '%Y%m%d'), | |
'details' => $activity['details'], | |
'status_id' => $activity['status_id'] == 2 ? 2 : 1, // If activity completed then case resolved, else ongoing | |
'is_deleted' => $activity['is_deleted'], // Unlikely, but for completeness | |
'contact_id' => $activity['target_contact_id'], // Case clients | |
'creator_id' => $activity['source_contact_id'], | |
); | |
$case = civicrm_api3('Case', 'create', $case_params); | |
$case = civicrm_api3('Case', 'getsingle', array('id' => $case['id'])); | |
// Delete the default activities on the new case, except for things like Open Case. | |
foreach ($case['activities'] as $aid) { | |
$case_act = civicrm_api3('Activity', 'getsingle', array('id' => $aid)); | |
if ($case_act['activity_type_id'] > 39) { // Last reserved CiviCase-related activity type on our system | |
civicrm_api3('Activity', 'delete', array('id' => $aid)); | |
} | |
} | |
return $case['id']; | |
} | |
/** | |
* Move an activity into a case, change its type and custom fields | |
* | |
* @param array $activity Old activity details | |
* @param int $case_id New case ID | |
*/ | |
function move_activity_to($activity, $case_id) { | |
// Firstly attach the activity to the case as-is | |
$cca = array('activity_id' => $activity['id'], 'case_id' => $case_id); | |
CRM_Case_BAO_Case::processCaseActivity($cca); | |
// Change it to the new activity type and fill in the new custom fields | |
$activity['activity_type_id'] = 136; // Press Release: Published and AO informed | |
$activity['custom_445'] = $activity['custom_252']; // Media | |
// Not custom_446 (scope) as it doesn't have an equivalent on the old activity | |
$activity['custom_447'] = $activity['custom_251']; // Link | |
$activity = civicrm_api3('Activity', 'create', $activity); | |
// Remove the old custom fields from it that no longer apply | |
CRM_Core_DAO::executeQuery(" | |
DELETE FROM `civicrm_value_press_release_custom_data_506` | |
WHERE `entity_id` = %0 | |
", array( | |
array($activity['id'], 'Int'), | |
)); | |
} | |
function move_sent_activity($activity_id, $case_id) { | |
// Firstly attach the activity to the case as-is | |
$cca = array('activity_id' => $activity_id, 'case_id' => $case_id); | |
CRM_Case_BAO_Case::processCaseActivity($cca); | |
// Change it to the new activity type | |
$activity['activity_type_id'] = 133; // Press Release: Sent to School | |
$activity = civicrm_api3('Activity', 'create', $activity); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Please note, this is for example only- it contains IDs that are only meaningful to our organisation.