/** * create or update a Volunteer Commendation * * This function is invoked from within the web form layer * * @param array $params An assoc array of name/value pairs * - aid: activity id of an existing commendation to update * - cid: id of contact to be commended * - vid: id of project for which contact is to be commended * - details: text about the contact's exceptional volunteerism * @see self::requiredParamsArePresent for rules re required params * @return array Result of api.activity.create * @access public * @static */ public static function create(array $params) { // check required params if (!self::requiredParamsArePresent($params)) { CRM_Core_Error::fatal('Not enough data to create commendation object.'); } $activity_statuses = CRM_Activity_BAO_Activity::buildOptions('status_id', 'create'); $api_params = array('activity_type_id' => self::getActivityTypeId(), 'status_id' => CRM_Utils_Array::key('Completed', $activity_statuses)); $aid = CRM_Utils_Array::value('aid', $params); if ($aid) { $api_params['id'] = $aid; } $cid = CRM_Utils_Array::value('cid', $params); if ($cid) { $api_params['target_contact_id'] = $cid; } $vid = CRM_Utils_Array::value('vid', $params); if ($vid) { $project = CRM_Volunteer_BAO_Project::retrieveByID($vid); $api_params['subject'] = ts('Volunteer Commendation for %1', array('1' => $project->title, 'domain' => 'org.civicrm.volunteer')); $customFieldSpec = self::getCustomFields(); $volunteer_project_id_field_name = $customFieldSpec['volunteer_project_id']['custom_n']; $api_params[$volunteer_project_id_field_name] = $vid; } if (array_key_exists('details', $params)) { $api_params['details'] = CRM_Utils_Array::value('details', $params); } return civicrm_api3('Activity', 'create', $api_params); }
/** * Load needed JS, CSS and settings for the backend Volunteer Management UI */ public static function addResources($entity_id, $entity_table) { static $loaded = FALSE; $ccr = CRM_Core_Resources::singleton(); if ($loaded || $ccr->isAjaxMode()) { return; } $loaded = TRUE; $config = CRM_Core_Config::singleton(); // Vendor libraries $ccr->addScriptFile('civicrm', 'packages/backbone/json2.js', 100, 'html-header', FALSE); $ccr->addScriptFile('civicrm', 'packages/backbone/backbone-min.js', 120, 'html-header', FALSE); $ccr->addScriptFile('civicrm', 'packages/backbone/backbone.marionette.min.js', 125, 'html-header', FALSE); // Our stylesheet $ccr->addStyleFile('org.civicrm.volunteer', 'css/volunteer_app.css'); // Add all scripts for our js app $weight = 0; $baseDir = CRM_Extension_System::singleton()->getMapper()->keyToBasePath('org.civicrm.volunteer') . '/'; // This glob pattern will recurse the js directory up to 4 levels deep foreach (glob($baseDir . 'js/backbone/{*,*/*,*/*/*,*/*/*/*}.js', GLOB_BRACE) as $file) { $fileName = substr($file, strlen($baseDir)); $ccr->addScriptFile('org.civicrm.volunteer', $fileName, $weight++); } // Add our template CRM_Core_Smarty::singleton()->assign('isModulePermissionSupported', CRM_Core_Config::singleton()->userPermissionClass->isModulePermissionSupported()); CRM_Core_Region::instance('page-header')->add(array('template' => 'CRM/Volunteer/Form/Manage.tpl')); // Fetch event so we can set the default start time for needs // FIXME: Not the greatest for supporting non-events $entity = civicrm_api3(str_replace('civicrm_', '', $entity_table), 'getsingle', array('id' => $entity_id)); // Static variables $ccr->addSetting(array('pseudoConstant' => array('volunteer_need_visibility' => array_flip(CRM_Volunteer_BAO_Need::buildOptions('visibility_id', 'validate')), 'volunteer_role' => CRM_Volunteer_BAO_Need::buildOptions('role_id', 'get'), 'volunteer_status' => CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate')), 'volunteer' => array('default_date' => CRM_Utils_Array::value('start_date', $entity)), 'config' => array('timeInputFormat' => $config->timeInputFormat), 'constants' => array('CRM_Core_Action' => array('NONE' => 0, 'ADD' => 1, 'UPDATE' => 2, 'VIEW' => 4, 'DELETE' => 8, 'BROWSE' => 16, 'ENABLE' => 32, 'DISABLE' => 64, 'EXPORT' => 128, 'BASIC' => 256, 'ADVANCED' => 512, 'PREVIEW' => 1024, 'FOLLOWUP' => 2048, 'MAP' => 4096, 'PROFILE' => 8192, 'COPY' => 16384, 'RENEW' => 32768, 'DETACH' => 65536, 'REVERT' => 131072, 'CLOSE' => 262144, 'REOPEN' => 524288, 'MAX_ACTION' => 1048575)))); // Check for problems _volunteer_checkResourceUrl(); }
/** * Load needed JS, CSS and settings for the backend Volunteer Management UI */ public static function addResources($entity_id, $entity_table) { static $loaded = FALSE; if ($loaded) { return; } $loaded = TRUE; $config = CRM_Core_Config::singleton(); $ccr = CRM_Core_Resources::singleton(); // Vendor libraries $ccr->addScriptFile('civicrm', 'packages/backbone/json2.js', 100, 'html-header', FALSE); $ccr->addScriptFile('civicrm', 'packages/backbone/backbone-min.js', 120, 'html-header'); $ccr->addScriptFile('civicrm', 'packages/backbone/backbone.marionette.min.js', 125, 'html-header', FALSE); // Our stylesheet $ccr->addStyleFile('org.civicrm.volunteer', 'css/volunteer_app.css'); // Add all scripts for our js app $weight = 0; $baseDir = CRM_Extension_System::singleton()->getMapper()->keyToBasePath('org.civicrm.volunteer') . '/'; // This glob pattern will recurse the js directory up to 4 levels deep foreach (glob($baseDir . 'js/{*,*/*,*/*/*,*/*/*/*}.js', GLOB_BRACE) as $file) { $fileName = substr($file, strlen($baseDir)); $ccr->addScriptFile('org.civicrm.volunteer', $fileName, $weight++); } // Add our template CRM_Core_Smarty::singleton()->assign('isModulePermissionSupported', CRM_Core_Config::singleton()->userPermissionClass->isModulePermissionSupported()); CRM_Core_Region::instance('page-header')->add(array('template' => 'CRM/Volunteer/Form/Manage.tpl')); // Fetch event so we can set the default start time for needs // FIXME: Not the greatest for supporting non-events $entity = civicrm_api3(str_replace('civicrm_', '', $entity_table), 'getsingle', array('id' => $entity_id)); // Static variables $ccr->addSetting(array('pseudoConstant' => array('volunteer_need_visibility' => array_flip(CRM_Volunteer_BAO_Need::buildOptions('visibility_id', 'validate')), 'volunteer_role' => CRM_Volunteer_BAO_Need::buildOptions('role_id', 'get'), 'volunteer_status' => CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate')), 'volunteer' => array('default_date' => CRM_Utils_Array::value('start_date', $entity)), 'config' => array('timeInputFormat' => $config->timeInputFormat))); // Check for problems _volunteer_civicrm_check_resource_url(); }
/** * Adjust Metadata for Create action * * The metadata is used for setting defaults, documentation & validation * @param array $params array or parameters determined by getfields */ function _civicrm_api3_volunteer_assignment_create_spec(&$params) { $params['volunteer_need_id']['api.required'] = 1; $params['assignee_contact_id']['api.required'] = 1; $params['assignee_contact_id']['api.aliases'] = array('contact_id'); $volunteerStatus = CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate'); $params['status_id']['api.default'] = array_search('Scheduled', $volunteerStatus); }
/** * This function will return the needed pieces to load up the backbone/ * marionette project backend from within an angular page. * * @param array $params * Not presently used. * @return array * Keyed with "css," "templates," "scripts," and "settings," this array * contains the dependencies of the backbone-based volunteer app. * */ function civicrm_api3_volunteer_util_loadbackbone($params) { $results = array("css" => array(), "templates" => array(), "scripts" => array(), "settings" => array()); $ccr = CRM_Core_Resources::singleton(); $config = CRM_Core_Config::singleton(); $results['css'][] = $ccr->getUrl('org.civicrm.volunteer', 'css/volunteer_app.css'); $baseDir = CRM_Extension_System::singleton()->getMapper()->keyToBasePath('org.civicrm.volunteer') . '/'; // This glob pattern will recurse the js directory up to 4 levels deep foreach (glob($baseDir . 'js/{*,*/*,*/*/*,*/*/*/*}.js', GLOB_BRACE) as $file) { $fileName = substr($file, strlen($baseDir)); $results['scripts'][] = $ccr->getUrl('org.civicrm.volunteer', $fileName); } $results['templates'][] = 'civicrm/volunteer/backbonetemplates'; $results['settings'] = array('pseudoConstant' => array('volunteer_need_visibility' => array_flip(CRM_Volunteer_BAO_Need::buildOptions('visibility_id', 'validate')), 'volunteer_role' => CRM_Volunteer_BAO_Need::buildOptions('role_id', 'get'), 'volunteer_status' => CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate')), 'volunteer' => array('default_date' => date("Y-m-d H:i:s", strtotime('tomorrow noon'))), 'config' => array('timeInputFormat' => $config->timeInputFormat), 'constants' => array('CRM_Core_Action' => array('NONE' => 0, 'ADD' => 1, 'UPDATE' => 2, 'VIEW' => 4, 'DELETE' => 8, 'BROWSE' => 16, 'ENABLE' => 32, 'DISABLE' => 64, 'EXPORT' => 128, 'BASIC' => 256, 'ADVANCED' => 512, 'PREVIEW' => 1024, 'FOLLOWUP' => 2048, 'MAP' => 4096, 'PROFILE' => 8192, 'COPY' => 16384, 'RENEW' => 32768, 'DETACH' => 65536, 'REVERT' => 131072, 'CLOSE' => 262144, 'REOPEN' => 524288, 'MAX_ACTION' => 1048575))); return civicrm_api3_create_success($results, "VolunteerUtil", "loadbackbone", $params); }
/** * Get a list of Assignments matching the params, where each param key is: * 1. the key of a field in civicrm_activity * except for activity_type_id and activity_duration * 2. the key of a custom field on the activity * (volunteer_need_id, time_scheduled, time_completed) * 3. the key of a field in civicrm_contact * 4. project_id * * @param array $params * @return array of CRM_Volunteer_BAO_Project objects */ static function retrieve(array $params) { $activity_fields = CRM_Activity_DAO_Activity::fields(); $contact_fields = CRM_Contact_DAO_Contact::fields(); $custom_fields = self::getCustomFields(); $foreign_fields = array('project_id', 'target_contact_id'); // This is the "real" id $activity_fields['id'] = $activity_fields['activity_id']; unset($activity_fields['activity_id']); // enforce restrictions on parameters $allowed_params = array_flip(array_merge(array_keys($activity_fields), array_keys($contact_fields), array_keys($custom_fields), $foreign_fields)); unset($allowed_params['activity_type_id']); unset($allowed_params['activity_duration']); $filtered_params = array_intersect_key($params, $allowed_params); $custom_group = self::getCustomGroup(); $customTableName = $custom_group['table_name']; foreach ($custom_fields as $name => $field) { $selectClause[] = "{$customTableName}.{$field['column_name']} AS {$name}"; } $customSelect = implode(', ', $selectClause); $activityContactTypes = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name'); $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContactTypes); $targetID = CRM_Utils_Array::key('Activity Targets', $activityContactTypes); $volunteerStatus = CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate'); $available = CRM_Utils_Array::key('Available', $volunteerStatus); $scheduled = CRM_Utils_Array::key('Scheduled', $volunteerStatus); $placeholders = array(1 => array($assigneeID, 'Integer'), 2 => array(self::volunteerActivityTypeId(), 'Integer'), 3 => array($scheduled, 'Integer'), 4 => array($available, 'Integer'), 5 => array($targetID, 'Integer')); $i = count($placeholders) + 1; $where = array(); $whereClause = NULL; foreach ($filtered_params as $key => $value) { if (CRM_Utils_Array::value($key, $activity_fields)) { $dataType = CRM_Utils_Type::typeToString($activity_fields[$key]['type']); $fieldName = $activity_fields[$key]['name']; $tableName = CRM_Activity_DAO_Activity::$_tableName; } elseif (CRM_Utils_Array::value($key, $contact_fields)) { $dataType = CRM_Utils_Type::typeToString($contact_fields[$key]['type']); $fieldName = $contact_fields[$key]['name']; $tableName = CRM_Contact_DAO_Contact::$_tableName; } elseif (CRM_Utils_Array::value($key, $custom_fields)) { $dataType = $custom_fields[$key]['data_type']; $fieldName = $custom_fields[$key]['column_name']; $tableName = $customTableName; } elseif ($key == 'project_id') { $dataType = 'Int'; $fieldName = 'id'; $tableName = CRM_Volunteer_DAO_Project::$_tableName; } elseif ($key == 'target_contact_id') { $dataType = 'Int'; $fieldName = 'contact_id'; $tableName = 'tgt'; // this is an alias for civicrm_activity_contact } $where[] = "{$tableName}.{$fieldName} = %{$i}"; $placeholders[$i] = array($value, $dataType); $i++; } if (count($where)) { $whereClause = 'AND ' . implode("\nAND ", $where); } $query = "\n SELECT\n civicrm_activity.*,\n assignee.contact_id AS assignee_contact_id,\n {$customSelect},\n civicrm_volunteer_need.start_time,\n civicrm_volunteer_need.is_flexible,\n civicrm_volunteer_need.role_id,\n assignee_contact.sort_name AS assignee_sort_name,\n assignee_contact.display_name AS assignee_display_name,\n assignee_phone.phone AS assignee_phone,\n assignee_phone.phone_ext AS assignee_phone_ext,\n assignee_email.email AS assignee_email,\n -- begin target contact fields\n tgt.contact_id AS target_contact_id,\n tgt_contact.sort_name AS target_sort_name,\n tgt_contact.display_name AS target_display_name,\n tgt_phone.phone AS target_phone,\n tgt_phone.phone_ext AS target_phone_ext,\n tgt_email.email AS target_email\n -- end target contact fields\n FROM civicrm_activity\n INNER JOIN civicrm_activity_contact assignee\n ON (\n assignee.activity_id = civicrm_activity.id\n AND assignee.record_type_id = %1\n )\n INNER JOIN civicrm_contact assignee_contact\n ON assignee.contact_id = assignee_contact.id\n LEFT JOIN civicrm_email assignee_email\n ON assignee_email.contact_id = assignee_contact.id AND assignee_email.is_primary = 1\n LEFT JOIN civicrm_phone assignee_phone\n ON assignee_phone.contact_id = assignee_contact.id AND assignee_phone.is_primary = 1\n -- begin target contact joins\n LEFT JOIN civicrm_activity_contact tgt\n ON (\n tgt.activity_id = civicrm_activity.id\n AND tgt.record_type_id = %5\n )\n LEFT JOIN civicrm_contact tgt_contact\n ON tgt.contact_id = tgt_contact.id\n LEFT JOIN civicrm_email tgt_email\n ON tgt_email.contact_id = tgt_contact.id AND tgt_email.is_primary = 1\n LEFT JOIN civicrm_phone tgt_phone\n ON tgt_phone.contact_id = tgt_contact.id AND tgt_phone.is_primary = 1\n -- end target contact joins\n INNER JOIN {$customTableName}\n ON ({$customTableName}.entity_id = civicrm_activity.id)\n INNER JOIN civicrm_volunteer_need\n ON (civicrm_volunteer_need.id = {$customTableName}.{$custom_fields['volunteer_need_id']['column_name']})\n INNER JOIN civicrm_volunteer_project\n ON (civicrm_volunteer_project.id = civicrm_volunteer_need.project_id)\n WHERE civicrm_activity.activity_type_id = %2\n AND civicrm_activity.status_id IN (%3, %4 )\n {$whereClause}\n "; $dao = CRM_Core_DAO::executeQuery($query, $placeholders); $rows = array(); while ($dao->fetch()) { $rows[$dao->id] = $dao->toArray(); } /* * For clarity we want the fields associated with each contact prefixed with * the contact type (e.g., target_phone). For backwards compatibility, * however, we want the fields associated with each assignee contact to be * accessible sans prefix. Eventually we should deprecate the non-prefixed * field names. */ foreach ($rows as $id => $fields) { foreach ($fields as $key => $value) { if (substr($key, 0, 9) == 'assignee_') { $rows[$id][substr($key, 9)] = $value; } } } return $rows; }
/** * Schedule message delivery for any contribution, regardless of type. */ public function scheduleForAny() { $actTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id'); $this->schedule->mapping_id = CRM_Activity_ActionMapping::ACTIVITY_MAPPING_ID; $this->schedule->start_action_date = 'receive_date'; $this->schedule->entity_value = CRM_Utils_Array::implodePadded(array_keys($actTypes)); $this->schedule->entity_status = CRM_Utils_Array::implodePadded(NULL); }
/** * @todo per totten's suggestion, wrap all these writes in a transaction; * see http://wiki.civicrm.org/confluence/display/CRMDOC43/Transaction+Reference */ function postProcess() { $cid = CRM_Utils_Array::value('userID', $_SESSION['CiviCRM'], NULL); $values = $this->controller->exportValues(); $profileFields = array(); foreach ($this->getProfileIDs() as $profileID) { $profileFields += CRM_Core_BAO_UFGroup::getFields($profileID); } $profileValues = array_intersect_key($values, $profileFields); $activityValues = array_diff_key($values, $profileValues); // Search for duplicate if (!$cid) { $dedupeParams = CRM_Dedupe_Finder::formatParams($profileValues, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); if ($ids) { $cid = $ids[0]; } } $cid = CRM_Contact_BAO_Contact::createProfileContact($profileValues, $profileFields, $cid); $activity_statuses = CRM_Activity_BAO_Activity::buildOptions('status_id', 'create'); $projectNeeds = array(); foreach ($this->_needs as $need) { $activityValues['volunteer_need_id'] = $need['id']; $activityValues['activity_date_time'] = CRM_Utils_Array::value('start_time', $need); $activityValues['assignee_contact_id'] = $cid; $activityValues['is_test'] = $this->_mode === 'test' ? 1 : 0; // below we assume that volunteers are always signing up only themselves; // for now this is a safe assumption, but we may need to revisit this. $activityValues['source_contact_id'] = $cid; // Set status to Available if user selected Flexible Need, else set to Scheduled. if (CRM_Utils_Array::value('is_flexible', $need)) { $activityValues['status_id'] = CRM_Utils_Array::key('Available', $activity_statuses); } else { $activityValues['status_id'] = CRM_Utils_Array::key('Scheduled', $activity_statuses); } $activityValues['time_scheduled_minutes'] = CRM_Utils_Array::value('duration', $need); CRM_Volunteer_BAO_Assignment::createVolunteerActivity($activityValues); if (!array_key_exists($need['project_id'], $projectNeeds)) { $projectNeeds[$need['project_id']] = array(); } $need['role'] = $need['role_label']; $need['description'] = $need['role_description']; $need['duration'] = CRM_Utils_Array::value('duration', $need); $projectNeeds[$need['project_id']][$need['id']] = $need; } // Send confirmation email to volunteer list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($cid); list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); if ($email) { $tplParams = $this->prepareTplParams($projectNeeds); $sendTemplateParams = array('contactId' => $cid, 'from' => "{$domainEmailName} <" . $domainEmailAddress . ">", 'groupName' => 'msg_tpl_workflow_volunteer', 'isTest' => $this->_mode === 'test', 'toName' => $displayName, 'toEmail' => $email, 'tplParams' => array("volunteer_projects" => $tplParams), 'valueName' => 'volunteer_registration'); $bcc = array(); foreach ($tplParams as $data) { foreach ($data['contacts'] as $manager) { $bcc[$manager['contact_id']] = "{$manager['display_name']} <{$manager['email']}>"; } } if (count($bcc)) { $sendTemplateParams['bcc'] = implode(', ', $bcc); } CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); } $statusMsg = ts('You are scheduled to volunteer. Thank you!', array('domain' => 'org.civicrm.volunteer')); CRM_Core_Session::setStatus($statusMsg, '', 'success'); CRM_Utils_System::redirect($this->_destination); }
public function testSequence() { $actStatuses = array_flip(\CRM_Core_PseudoConstant::activityStatus('name')); $caseStatuses = array_flip(\CRM_Case_PseudoConstant::caseStatus('name')); $actTypes = array_flip(\CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'create')); // Create case; schedule first activity \CRM_Utils_Time::setTime('2013-11-30 01:00:00'); $case = $this->callAPISuccess('case', 'create', $this->_params); $analyzer = new \Civi\CCase\Analyzer($case['id']); $this->assertEquals($caseStatuses['Open'], self::ag($analyzer->getCase(), 'status_id')); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertFalse($analyzer->hasActivity('Mental health evaluation')); $this->assertFalse($analyzer->hasActivity('Secure temporary housing')); // Edit details of first activity -- but don't finish it yet! \CRM_Utils_Time::setTime('2013-11-30 01:30:00'); $this->callApiSuccess('Activity', 'create', array('id' => self::ag($analyzer->getSingleActivity('Medical evaluation'), 'id'), 'subject' => 'This is the new subject')); $analyzer = new \Civi\CCase\Analyzer($case['id']); $this->assertEquals($caseStatuses['Open'], self::ag($analyzer->getCase(), 'status_id')); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertFalse($analyzer->hasActivity('Mental health evaluation')); $this->assertFalse($analyzer->hasActivity('Secure temporary housing')); // Complete first activity; schedule second \CRM_Utils_Time::setTime('2013-11-30 02:00:00'); $this->callApiSuccess('Activity', 'create', array('id' => self::ag($analyzer->getSingleActivity('Medical evaluation'), 'id'), 'status_id' => $actStatuses['Completed'])); $analyzer->flush(); $this->assertEquals($caseStatuses['Open'], self::ag($analyzer->getCase(), 'status_id')); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 02:00:00', self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'status_id')); $this->assertFalse($analyzer->hasActivity('Secure temporary housing')); // Complete second activity; schedule third \CRM_Utils_Time::setTime('2013-11-30 03:00:00'); $this->callApiSuccess('Activity', 'create', array('id' => self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'id'), 'status_id' => $actStatuses['Completed'])); $analyzer->flush(); $this->assertEquals($caseStatuses['Open'], self::ag($analyzer->getCase(), 'status_id')); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 02:00:00', self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 03:00:00', self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'status_id')); //Add an Activity before the case is closed \CRM_Utils_Time::setTime('2013-11-30 04:00:00'); $this->callApiSuccess('Activity', 'create', array('activity_name' => 'Follow up', 'activity_type_id' => $actTypes['Follow up'], 'status_id' => $actStatuses['Scheduled'], 'case_id' => $case['id'], 'activity_date_time' => \CRM_Utils_Time::getTime())); $analyzer->flush(); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 02:00:00', self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 03:00:00', self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'status_id')); $this->assertApproxTime('2013-11-30 04:00:00', self::ag($analyzer->getSingleActivity('Follow up'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Follow up'), 'status_id')); // Complete third activity; Case should remain open because of the Follow up activity \CRM_Utils_Time::setTime('2013-11-30 04:00:00'); $this->callApiSuccess('Activity', 'create', array('id' => self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'id'), 'status_id' => $actStatuses['Completed'])); $analyzer->flush(); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 02:00:00', self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 03:00:00', self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'status_id')); $this->assertApproxTime('2013-11-30 04:00:00', self::ag($analyzer->getSingleActivity('Follow up'), 'activity_date_time')); $this->assertEquals($actStatuses['Scheduled'], self::ag($analyzer->getSingleActivity('Follow up'), 'status_id')); $this->assertEquals($caseStatuses['Open'], self::ag($analyzer->getCase(), 'status_id')); // Complete the additional Activity; Case closed \CRM_Utils_Time::setTime('2013-11-30 04:00:00'); $this->callApiSuccess('Activity', 'create', array('id' => self::ag($analyzer->getSingleActivity('Follow up'), 'id'), 'status_id' => $actStatuses['Completed'])); $analyzer->flush(); $this->assertApproxTime('2013-11-30 01:00:00', self::ag($analyzer->getSingleActivity('Medical evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Medical evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 02:00:00', self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Mental health evaluation'), 'status_id')); $this->assertApproxTime('2013-11-30 03:00:00', self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Secure temporary housing'), 'status_id')); $this->assertApproxTime('2013-11-30 04:00:00', self::ag($analyzer->getSingleActivity('Follow up'), 'activity_date_time')); $this->assertEquals($actStatuses['Completed'], self::ag($analyzer->getSingleActivity('Follow up'), 'status_id')); $this->assertEquals($caseStatuses['Closed'], self::ag($analyzer->getCase(), 'status_id')); }
/** * Set default values for the form. * * @access public * * @return None */ function setDefaultValues() { $defaults = array(); $i = 1; $volunteerRole = CRM_Volunteer_BAO_Need::buildOptions('role_id', 'create'); $volunteerStatus = CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate'); foreach ($this->_volunteerData as $data) { $defaults['field'][$i]['scheduled_duration'] = $data['time_scheduled_minutes']; $defaults['field'][$i]['actual_duration'] = $data['time_completed_minutes']; $defaults['field'][$i]['volunteer_role'] = CRM_Utils_Array::value($data['volunteer_role_id'], $volunteerRole); $defaults['field'][$i]['volunteer_status'] = $data['status_id']; $defaults['field'][$i]['activity_id'] = $data['id']; $defaults['field'][$i]['start_date'] = CRM_Utils_Date::customFormat($data['activity_date_time'], "%m/%E/%Y %l:%M %P"); $defaults['field'][$i]["contact_id"] = $data['contact_id']; $i++; } $completed = CRM_Utils_Array::key('Completed', $volunteerStatus); for ($j = $i; $j < $this->_batchInfo['item_count']; $j++) { $defaults['field'][$j]['volunteer_status'] = $completed; $startDate = CRM_Utils_Date::customFormat($this->_start_date, "%m/%E/%Y %l:%M %P"); $date = explode(' ', $startDate); $defaults['field'][$j]['start_date'] = $date[0]; $defaults['field'][$j]['start_date_time'] = $date[1]; } return $defaults; }
/** * Check for required params. * * @param array $params * Associated array of fields. * * @throws API_Exception * @throws Exception * @return array * array with errors */ function _civicrm_api3_activity_check_params(&$params) { $contactIDFields = array_intersect_key($params, array('source_contact_id' => 1, 'assignee_contact_id' => 1, 'target_contact_id' => 1)); // this should be handled by wrapper layer & probably the api would already manage it //correctly by doing post validation - ie. a failure should result in a roll-back = an error // needs testing if (!empty($contactIDFields)) { $contactIds = array(); foreach ($contactIDFields as $fieldname => $contactfield) { if (empty($contactfield)) { continue; } if (is_array($contactfield)) { foreach ($contactfield as $contactkey => $contactvalue) { $contactIds[$contactvalue] = $contactvalue; } } else { $contactIds[$contactfield] = $contactfield; } } $sql = ' SELECT count(*) FROM civicrm_contact WHERE id IN (' . implode(', ', $contactIds) . ' )'; if (count($contactIds) != CRM_Core_DAO::singleValueQuery($sql)) { throw new API_Exception('Invalid Contact Id'); } } $activityIds = array('activity' => CRM_Utils_Array::value('id', $params), 'parent' => CRM_Utils_Array::value('parent_id', $params), 'original' => CRM_Utils_Array::value('original_id', $params)); foreach ($activityIds as $id => $value) { if ($value && !CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $value, 'id')) { throw new API_Exception('Invalid ' . ucfirst($id) . ' Id'); } } // this should be handled by wrapper layer & probably the api would already manage it //correctly by doing pseudoconstant validation // needs testing $activityTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'validate'); $activityName = CRM_Utils_Array::value('activity_name', $params); $activityName = ucfirst($activityName); $activityLabel = CRM_Utils_Array::value('activity_label', $params); if ($activityLabel) { $activityTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'create'); } $activityTypeId = CRM_Utils_Array::value('activity_type_id', $params); if ($activityName || $activityLabel) { $activityTypeIdInList = array_search($activityName ? $activityName : $activityLabel, $activityTypes); if (!$activityTypeIdInList) { $errorString = $activityName ? "Invalid Activity Name : {$activityName}" : "Invalid Activity Type Label"; throw new Exception($errorString); } elseif ($activityTypeId && $activityTypeId != $activityTypeIdInList) { throw new API_Exception('Mismatch in Activity'); } $params['activity_type_id'] = $activityTypeIdInList; } elseif ($activityTypeId && !array_key_exists($activityTypeId, $activityTypes)) { throw new API_Exception('Invalid Activity Type ID'); } // check for activity duration minutes // this should be validated @ the wrapper layer not here // needs testing if (isset($params['duration_minutes']) && !is_numeric($params['duration_minutes'])) { throw new API_Exception('Invalid Activity Duration (in minutes)'); } //if adding a new activity & date_time not set make it now // this should be managed by the wrapper layer & setting ['api.default'] in speces // needs testing if (empty($params['id']) && empty($params['activity_date_time'])) { $params['activity_date_time'] = CRM_Utils_Date::processDate(date('Y-m-d H:i:s')); } return NULL; }
/** * @todo per totten's suggestion, wrap all these writes in a transaction; * see http://wiki.civicrm.org/confluence/display/CRMDOC43/Transaction+Reference */ function postProcess() { $cid = CRM_Utils_Array::value('userID', $_SESSION['CiviCRM'], NULL); $values = $this->controller->exportValues(); $isFlexible = FALSE; // Role id is not present in form $values when the only public need is the flexible need. // So if role id is not set OR if it matches flexible role id constant then use the flexible need id if (!isset($values['volunteer_role_id']) || (int) CRM_Utils_Array::value('volunteer_role_id', $values) === CRM_Volunteer_BAO_Need::FLEXIBLE_ROLE_ID) { $isFlexible = TRUE; foreach ($this->_project->needs as $n) { if ($n['is_flexible'] === '1') { $values['volunteer_need_id'] = $n['id']; break; } } } unset($values['volunteer_role_id']); // we don't need this anymore $params = array('id' => CRM_Utils_Array::value('volunteer_need_id', $values), 'version' => 3); $need = civicrm_api('VolunteerNeed', 'getsingle', $params); $profile_fields = CRM_Core_BAO_UFGroup::getFields($this->_ufgroup_id); $profile_values = array_intersect_key($values, $profile_fields); $builtin_values = array_diff_key($values, $profile_values); // Search for duplicate if (!$cid) { $dedupeParams = CRM_Dedupe_Finder::formatParams($profile_values, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); if ($ids) { $cid = $ids[0]; } } $cid = CRM_Contact_BAO_Contact::createProfileContact($profile_values, $profile_fields, $cid, NULL, $this->_ufgroup_id); $activity_statuses = CRM_Activity_BAO_Activity::buildOptions('status_id', 'create'); $builtin_values['activity_date_time'] = CRM_Utils_Array::value('start_time', $need); $builtin_values['assignee_contact_id'] = $cid; $builtin_values['is_test'] = $this->_mode === 'test' ? 1 : 0; // below we assume that volunteers are always signing up only themselves; // for now this is a safe assumption, but we may need to revisit this. $builtin_values['source_contact_id'] = $cid; // Set status to Available if user selected Flexible Need, else set to Scheduled. if ($isFlexible) { $builtin_values['status_id'] = CRM_Utils_Array::key('Available', $activity_statuses); } else { $builtin_values['status_id'] = CRM_Utils_Array::key('Scheduled', $activity_statuses); } $builtin_values['subject'] = $this->_project->title; $builtin_values['time_scheduled_minutes'] = CRM_Utils_Array::value('duration', $need); CRM_Volunteer_BAO_Assignment::createVolunteerActivity($builtin_values); // Send confirmation email to volunteer list($displayName, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($cid); list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); if ($email) { $date = CRM_Utils_Date::customFormat($builtin_values['activity_date_time'], "%m/%E/%Y at %l:%M %P"); $html = "You are scheduled to volunteer at the " . $builtin_values["subject"] . " on " . $date . ". Thank You!"; $mailParams["from"] = "{$domainEmailName} <" . $domainEmailAddress . ">"; $mailParams["toName"] = $displayName; $mailParams["toEmail"] = $email; $mailParams["subject"] = "Volunteer Confirmation for {$builtin_values['subject']}"; $mailParams["text"] = $html; $mailParams["html"] = $html; $mailParams["replyTo"] = $domainEmailAddress; CRM_Utils_Mail::send($mailParams); } $statusMsg = ts('You are scheduled to volunteer. Thank you!', array('domain' => 'org.civicrm.volunteer')); CRM_Core_Session::setStatus($statusMsg, '', 'success'); CRM_Utils_System::redirect($this->_destination); }
/** * @todo per totten's suggestion, wrap all these writes in a transaction; * see http://wiki.civicrm.org/confluence/display/CRMDOC43/Transaction+Reference */ function postProcess() { $cid = CRM_Utils_Array::value('userID', $_SESSION['CiviCRM'], NULL); $values = $this->controller->exportValues(); $profileFields = array(); foreach ($this->getProfileIDs() as $profileID) { $profileFields += CRM_Core_BAO_UFGroup::getFields($profileID); } $profileValues = array_intersect_key($values, $profileFields); $activityValues = array_diff_key($values, $profileValues); // Search for duplicate if (!$cid) { $dedupeParams = CRM_Dedupe_Finder::formatParams($profileValues, 'Individual'); $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); if ($ids) { $cid = $ids[0]; } } $cid = CRM_Contact_BAO_Contact::createProfileContact($profileValues, $profileFields, $cid); $activity_statuses = CRM_Activity_BAO_Activity::buildOptions('status_id', 'create'); foreach ($this->_needs as $need) { $activityValues['volunteer_need_id'] = $need['id']; $activityValues['activity_date_time'] = CRM_Utils_Array::value('start_time', $need); $activityValues['assignee_contact_id'] = $cid; $activityValues['is_test'] = $this->_mode === 'test' ? 1 : 0; // below we assume that volunteers are always signing up only themselves; // for now this is a safe assumption, but we may need to revisit this. $activityValues['source_contact_id'] = $cid; // Set status to Available if user selected Flexible Need, else set to Scheduled. if (CRM_Utils_Array::value('is_flexible', $need)) { $activityValues['status_id'] = CRM_Utils_Array::key('Available', $activity_statuses); } else { $activityValues['status_id'] = CRM_Utils_Array::key('Scheduled', $activity_statuses); } $activityValues['time_scheduled_minutes'] = CRM_Utils_Array::value('duration', $need); CRM_Volunteer_BAO_Assignment::createVolunteerActivity($activityValues); } $statusMsg = ts('You are scheduled to volunteer. Thank you!', array('domain' => 'org.civicrm.volunteer')); CRM_Core_Session::setStatus($statusMsg, '', 'success'); CRM_Utils_System::redirect($this->_destination); }
/** * Get the list of absence-related activity status * * @return array (int activity_status_id => string activity_status_label) */ public static function getActivityStatus($return = 'label') { $activityStatus = CRM_Activity_BAO_Activity::buildOptions('status_id', 'validate'); $absenceStatus = array('Scheduled' => ts('Requested'), 'Completed' => ts('Approved'), 'Cancelled' => ts('Cancelled'), 'Rejected' => ts('Rejected')); $result = array(); foreach ($absenceStatus as $name => $title) { if ($key = CRM_Utils_Array::key($name, $activityStatus)) { $result[$key] = $title; if ($return == 'name') { $result[$key] = $name; } } } return $result; }
/** * This function Loops through the needs the user is signing up for * and creates activity records for them. * * @param int $cid * The contact ID for whom this activity is to be created * @param array $activityValues * An array of values corresponding to the data the user submitted minus the profile fields * @return array * Project needs data for use in sending confirmation email. */ private function createVolunteerActivity($cid, array $activityValues) { $projectNeeds = array(); $activity_statuses = CRM_Activity_BAO_Activity::buildOptions('status_id', 'create'); foreach ($this->_needs as $need) { $activityValues['volunteer_need_id'] = $need['id']; $activityValues['activity_date_time'] = CRM_Utils_Array::value('start_time', $need); $activityValues['assignee_contact_id'] = $cid; $activityValues['is_test'] = $this->_mode === 'test' ? 1 : 0; $activityValues['source_contact_id'] = $this->_primary_volunteer_id; // Set status to Available if user selected Flexible Need, else set to Scheduled. if (CRM_Utils_Array::value('is_flexible', $need)) { $activityValues['status_id'] = CRM_Utils_Array::key('Available', $activity_statuses); } else { $activityValues['status_id'] = CRM_Utils_Array::key('Scheduled', $activity_statuses); } $activityValues['time_scheduled_minutes'] = CRM_Utils_Array::value('duration', $need); CRM_Volunteer_BAO_Assignment::createVolunteerActivity($activityValues); if (!array_key_exists($need['project_id'], $projectNeeds)) { $projectNeeds[$need['project_id']] = array(); } $need['role'] = $need['role_label']; $need['description'] = $need['role_description']; $need['duration'] = CRM_Utils_Array::value('duration', $need); $projectNeeds[$need['project_id']][$need['id']] = $need; } return $projectNeeds; }