$value) { $varName = '_' . $name; $this->$varName = $value; } } /** * Split a large array of contactIDs into more manageable smaller chunks. */ public function &splitContactIDs(&$contactIDs) { // contactIDs could be a real large array, so we split it up into // smaller chunks and then general xml for each chunk $chunks = array(); $current = 0; $chunks[$current] = array(); $count = 0; foreach ($contactIDs as $k => $v) { $chunks[$current][$k] = $v; $count++; if ($count == self::CHUNK_SIZE) { $current++; $chunks[$current] = array(); $count = 0; } } if (empty($chunks[$current])) { unset($chunks[$current]); } return $chunks; } /** * Given a set of contact IDs get the values. */ public function getValues(&$contactIDs, &$additionalContactIDs) { $this->contact($contactIDs); $this->address($contactIDs); $this->phone($contactIDs); $this->email($contactIDs); $this->im($contactIDs); $this->website($contactIDs); $this->note($contactIDs); $this->group($contactIDs); $this->groupContact($contactIDs); $this->savedSearch($contactIDs); $this->tag($contactIDs); $this->entityTag($contactIDs); $this->relationship($contactIDs, $additionalContactIDs); $this->activity($contactIDs, $additionalContactIDs); } public function metaData() { $optionGroupVars = array( 'prefix_id' => 'individual_prefix', 'suffix_id' => 'individual_suffix', 'gender_id' => 'gender', 'mobile_provider' => 'mobile_provider', 'phone_type' => 'phone_type', 'activity_type' => 'activity_type', 'status_id' => 'activity_status_id', 'priority_id' => 'activity_priority_id', 'medium_id' => 'encounter_medium', 'communication_style_id' => 'communication_style', 'email_greeting' => 'email_greeting', 'postal_greeting' => 'postal_greeting', 'addressee_id' => 'addressee', ); $this->optionGroup($optionGroupVars); $auxilaryTables = array( 'civicrm_location_type' => 'CRM_Core_DAO_LocationType', 'civicrm_relationship_type' => 'CRM_Contact_DAO_RelationshipType', ); $this->auxTable($auxilaryTables); } /** * @param $tables */ public function auxTable($tables) { foreach ($tables as $tableName => $daoName) { $fields = &$this->dbFields($daoName, TRUE); $sql = "SELECT * from $tableName"; $this->sql($sql, $tableName, $fields); } } /** * @param $optionGroupVars */ public function optionGroup($optionGroupVars) { $names = array_values($optionGroupVars); $str = array(); foreach ($names as $name) { $str[] = "'$name'"; } $nameString = implode(",", $str); $sql = " SELECT * FROM civicrm_option_group WHERE name IN ( $nameString ) "; $fields = &$this->dbFields('CRM_Core_DAO_OptionGroup', TRUE); $this->sql($sql, 'civicrm_option_group', $fields); $sql = " SELECT v.* FROM civicrm_option_value v INNER JOIN civicrm_option_group g ON v.option_group_id = g.id WHERE g.name IN ( $nameString ) "; $fields = &$this->dbFields('CRM_Core_DAO_OptionValue', TRUE); $this->sql($sql, 'civicrm_option_value', $fields); } /** * @param $ids * @param string $tableName * @param $fields * @param $whereField * @param null $additionalWhereCond */ public function table( &$ids, $tableName, &$fields, $whereField, $additionalWhereCond = NULL ) { if (empty($ids)) { return; } $idString = implode(',', $ids); $sql = " SELECT * FROM $tableName WHERE $whereField IN ( $idString ) "; if ($additionalWhereCond) { $sql .= " AND $additionalWhereCond"; } $this->sql($sql, $tableName, $fields); } /** * @param $sql * @param string $tableName * @param $fields */ public function sql($sql, $tableName, &$fields) { $dao = &CRM_Core_DAO::executeQuery($sql); while ($dao->fetch()) { $value = array(); foreach ($fields as $name) { if (empty($dao->$name)) { $value[$name] = NULL; } else { $value[$name] = $dao->$name; } } $this->appendValue($dao->id, $tableName, $value); } $dao->free(); } /** * @param $contactIDs */ public function contact(&$contactIDs) { $fields = &$this->dbFields('CRM_Contact_DAO_Contact', TRUE); $this->table($contactIDs, 'civicrm_contact', $fields, 'id', NULL); } /** * @param $contactIDs */ public function note(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_Note', TRUE); $this->table($contactIDs, 'civicrm_note', $fields, 'entity_id', "entity_table = 'civicrm_contact'"); } /** * @param $contactIDs */ public function phone(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_Phone', TRUE); $this->table($contactIDs, 'civicrm_phone', $fields, 'contact_id', NULL); } /** * @param $contactIDs */ public function email(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_Email', TRUE); $this->table($contactIDs, 'civicrm_email', $fields, 'contact_id', NULL); } /** * @param $contactIDs */ public function im(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_IM', TRUE); $this->table($contactIDs, 'civicrm_im', $fields, 'contact_id', NULL); } /** * @param $contactIDs */ public function website(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_Website', TRUE); $this->table($contactIDs, 'civicrm_website', $fields, 'contact_id', NULL); } /** * @param $contactIDs */ public function address(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_Email', TRUE); $this->table($contactIDs, 'civicrm_address', $fields, 'contact_id', NULL); } /** * @param $contactIDs */ public function groupContact(&$contactIDs) { $fields = &$this->dbFields('CRM_Contact_DAO_GroupContact', TRUE); $this->table($contactIDs, 'civicrm_group_contact', $fields, 'contact_id', NULL); } /** * TODO - support group inheritance * Parent child group ids are encoded in a text string * @param $contactIDs */ public function group(&$contactIDs) { // handle groups only once static $_groupsHandled = array(); $ids = implode(',', $contactIDs); $sql = " SELECT DISTINCT group_id FROM civicrm_group_contact WHERE contact_id IN ( $ids ) "; $dao = CRM_Core_DAO::executeQuery($sql); $groupIDs = array(); while ($dao->fetch()) { if (!isset($_groupsHandled[$dao->group_id])) { $groupIDs[] = $dao->group_id; $_groupsHandled[$dao->group_id] = 1; } } $fields = &$this->dbFields('CRM_Contact_DAO_Group', TRUE); $this->table($groupIDs, 'civicrm_group', $fields, 'id'); $this->savedSearch($groupIDs); } /** * TODO - support search builder and custom saved searches * @param $groupIDs */ public function savedSearch(&$groupIDs) { if (empty($groupIDs)) { return; } $idString = implode(",", $groupIDs); $sql = " SELECT s.* FROM civicrm_saved_search s INNER JOIN civicrm_group g on g.saved_search_id = s.id WHERE g.id IN ( $idString ) "; $fields = &$this->dbFields('CRM_Contact_DAO_SavedSearch', TRUE); $this->sql($sql, 'civicrm_saved_search', $fields); } /** * @param $contactIDs */ public function entityTag(&$contactIDs) { $fields = &$this->dbFields('CRM_Core_DAO_EntityTag', TRUE); $this->table($contactIDs, 'civicrm_entity_tag', $fields, 'entity_id', "entity_table = 'civicrm_contact'"); } /** * @param $contactIDs */ public function tag(&$contactIDs) { // handle tags only once static $_tagsHandled = array(); $ids = implode(',', $contactIDs); $sql = " SELECT DISTINCT tag_id FROM civicrm_entity_tag WHERE entity_id IN ( $ids ) AND entity_table = 'civicrm_contact' "; $dao = CRM_Core_DAO::executeQuery($sql); $tagIDs = array(); while ($dao->fetch()) { if (!isset($_tagsHandled[$dao->tag_id])) { $tagIDs[] = $dao->tag_id; $_tagsHandled[$dao->tag_id] = 1; } } $fields = &$this->dbFields('CRM_Core_DAO_Tag', TRUE); $this->table($tagIDs, 'civicrm_tag', $fields, 'id'); } /** * @param $contactIDs * @param $additionalContacts */ public function relationship(&$contactIDs, &$additionalContacts) { // handle relationships only once static $_relationshipsHandled = array(); $ids = implode(',', $contactIDs); $sql = "( SELECT r.* FROM civicrm_relationship r WHERE r.contact_id_a IN ( $ids ) ) UNION ( SELECT r.* FROM civicrm_relationship r WHERE r.contact_id_b IN ( $ids ) ) "; $fields = $this->dbFields('CRM_Contact_DAO_Relationship', TRUE); $dao = &CRM_Core_DAO::executeQuery($sql); while ($dao->fetch()) { if (isset($_relationshipsHandled[$dao->id])) { continue; } $_relationshipsHandled[$dao->id] = $dao->id; $relationship = array(); foreach ($fields as $fld) { if (empty($dao->$fld)) { $relationship[$fld] = NULL; } else { $relationship[$fld] = $dao->$fld; } } $this->appendValue($dao->id, 'civicrm_relationship', $relationship); $this->addAdditionalContacts(array( $dao->contact_id_a, $dao->contact_id_b, ), $additionalContacts ); } $dao->free(); } /** * @param $contactIDs * @param $additionalContacts */ public function activity(&$contactIDs, &$additionalContacts) { static $_activitiesHandled = array(); $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name'); $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts); $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts); $ids = implode(',', $contactIDs); // query framing returning all contacts in valid activity $sql = " SELECT a.*, ac.id as acID, ac.activity_id, ac.contact_id, ac.record_type_id FROM civicrm_activity a INNER JOIN civicrm_activity_contact ac ON ac.activity_id = a.id WHERE ac.contact_id IN ( $ids ) AND (a.activity_type_id != 3 AND a.activity_type_id != 20) "; $fields = &$this->dbFields('CRM_Activity_DAO_Activity', TRUE); $dao = &CRM_Core_DAO::executeQuery($sql); while ($dao->fetch()) { // adding source, target and assignee contacts in additional contacts array $this->addAdditionalContacts(array($dao->contact_id), $additionalContacts ); // append values of activity contacts $activityContacts = array( 'id' => $dao->acID, 'contact_id' => $dao->contact_id, 'activity_id' => $dao->activity_id, 'record_type_id' => $dao->record_type_id, ); $this->appendValue($dao->acID, 'civicrm_activity_contact', $activityContacts); if (isset($_activitiesHandled[$dao->id])) { continue; } $_activitiesHandled[$dao->id] = $dao->id; $activity = array(); foreach ($fields as $fld) { if (empty($dao->$fld)) { $activity[$fld] = NULL; } else { $activity[$fld] = $dao->$fld; } } // append activity value $this->appendValue($dao->id, 'civicrm_activity', $activity); } $dao->free(); } /** * @param int $id * @param string $name * @param $value */ public function appendValue($id, $name, $value) { if (empty($value)) { return; } if (!isset($this->_values[$name])) { $this->_values[$name] = array(); $this->_values[$name][] = array_keys($value); } $this->_values[$name][] = array_values($value); } /** * @param string $daoName * @param bool $onlyKeys * * @return array */ public function dbFields($daoName, $onlyKeys = FALSE) { static $_fieldsRetrieved = array(); if (!isset($_fieldsRetrieved[$daoName])) { $_fieldsRetrieved[$daoName] = array(); $daoFile = str_replace('_', DIRECTORY_SEPARATOR, $daoName ) . '.php'; include_once $daoFile; $daoFields = &$daoName::fields(); foreach ($daoFields as $key => & $value) { $_fieldsRetrieved[$daoName][$value['name']] = array( 'uniqueName' => $key, 'type' => $value['type'], 'title' => CRM_Utils_Array::value('title', $value, NULL), ); } } if ($onlyKeys) { return array_keys($_fieldsRetrieved[$daoName]); } else { return $_fieldsRetrieved[$daoName]; } } /** * @param $contactIDs * @param $additionalContacts */ public function addAdditionalContacts($contactIDs, &$additionalContacts) { if (!$this->_discoverContacts) { return; } foreach ($contactIDs as $cid) { if ($cid && !isset($this->_allContactIDs[$cid]) && !isset($additionalContacts[$cid]) ) { $additionalContacts[$cid] = $cid; } } } /** * @param $contactIDs */ public function export(&$contactIDs) { $chunks = &$this->splitContactIDs($contactIDs); $additionalContactIDs = array(); foreach ($chunks as $chunk) { $this->getValues($chunk, $additionalContactIDs); } if (!empty($additionalContactIDs)) { $this->_allContactIDs = $this->_allContactIDs + $additionalContactIDs; $this->export($additionalContactIDs); } } /** * @param string $fileName * @param null $lastExportTime * @param bool $discoverContacts */ public function run( $fileName, $lastExportTime = NULL, $discoverContacts = FALSE ) { $this->_discoverContacts = $discoverContacts; if (!$lastExportTime) { $sql = " SELECT id FROM civicrm_contact "; } else { $sql = "( SELECT DISTINCT entity_id FROM civicrm_log WHERE entity_table = 'civicrm_contact' AND modified_date >= $lastExportTime ) UNION ( SELECT DISTINCT contact_id FROM civicrm_subscription_history WHERE date >= $lastExportTime ) "; } $dao = &CRM_Core_DAO::executeQuery($sql); $contactIDs = array(); while ($dao->fetch()) { $contactIDs[$dao->id] = $dao->id; } $this->_allContactIDs = $contactIDs; $this->_values = array(); $this->metaData(); $this->export($contactIDs); $json = json_encode($this->_values, JSON_NUMERIC_CHECK); file_put_contents($fileName, $json ); // print_r( json_decode( $json ) ); } }