Skip to content

Instantly share code, notes, and snippets.

@davidknoll
Created June 8, 2016 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidknoll/8ad934d8736459c98e445f91576c719d to your computer and use it in GitHub Desktop.
Save davidknoll/8ad934d8736459c98e445f91576c719d to your computer and use it in GitHub Desktop.
Bulk creation of Cases from Activities
#!/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);
}
@davidknoll
Copy link
Author

Please note, this is for example only- it contains IDs that are only meaningful to our organisation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment