3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
35 class CRM_Utils_Migrate_ExportJSON
{
36 const CHUNK_SIZE
= 128;
38 protected $_contactIDs;
40 protected $_allContactIDs;
44 protected $_discoverContacts = FALSE;
46 protected $_renameGroups = 1;
48 protected $_renameTags = 1;
50 protected $_sitePrefix = 'Site 1';
53 * @param array $params
55 public function __construct(&$params) {
56 foreach ($params as $name => $value) {
57 $varName = '_' . $name;
58 $this->$varName = $value;
63 * Split a large array of contactIDs into more manageable smaller chunks.
65 public function &splitContactIDs(&$contactIDs) {
66 // contactIDs could be a real large array, so we split it up into
67 // smaller chunks and then general xml for each chunk
70 $chunks[$current] = array();
73 foreach ($contactIDs as $k => $v) {
74 $chunks[$current][$k] = $v;
77 if ($count == self
::CHUNK_SIZE
) {
79 $chunks[$current] = array();
84 if (empty($chunks[$current])) {
85 unset($chunks[$current]);
92 * Given a set of contact IDs get the values.
94 public function getValues(&$contactIDs, &$additionalContactIDs) {
96 $this->contact($contactIDs);
97 $this->address($contactIDs);
98 $this->phone($contactIDs);
99 $this->email($contactIDs);
100 $this->im($contactIDs);
101 $this->website($contactIDs);
102 $this->note($contactIDs);
104 $this->group($contactIDs);
105 $this->groupContact($contactIDs);
106 $this->savedSearch($contactIDs);
108 $this->tag($contactIDs);
109 $this->entityTag($contactIDs);
111 $this->relationship($contactIDs, $additionalContactIDs);
112 $this->activity($contactIDs, $additionalContactIDs);
115 public function metaData() {
116 $optionGroupVars = array(
117 'prefix_id' => 'individual_prefix',
118 'suffix_id' => 'individual_suffix',
119 'gender_id' => 'gender',
120 'mobile_provider' => 'mobile_provider',
121 'phone_type' => 'phone_type',
122 'activity_type' => 'activity_type',
123 'status_id' => 'activity_status_id',
124 'priority_id' => 'activity_priority_id',
125 'medium_id' => 'encounter_medium',
126 'communication_style_id' => 'communication_style',
127 'email_greeting' => 'email_greeting',
128 'postal_greeting' => 'postal_greeting',
129 'addressee_id' => 'addressee',
131 $this->optionGroup($optionGroupVars);
133 $auxilaryTables = array(
134 'civicrm_location_type' => 'CRM_Core_DAO_LocationType',
135 'civicrm_relationship_type' => 'CRM_Contact_DAO_RelationshipType',
137 $this->auxTable($auxilaryTables);
143 public function auxTable($tables) {
144 foreach ($tables as $tableName => $daoName) {
145 $fields = &$this->dbFields($daoName, TRUE);
147 $sql = "SELECT * from $tableName";
148 $this->sql($sql, $tableName, $fields);
153 * @param $optionGroupVars
155 public function optionGroup($optionGroupVars) {
156 $names = array_values($optionGroupVars);
158 foreach ($names as $name) {
161 $nameString = implode(",", $str);
165 FROM civicrm_option_group
166 WHERE name IN ( $nameString )
168 $fields = &$this->dbFields('CRM_Core_DAO_OptionGroup', TRUE);
169 $this->sql($sql, 'civicrm_option_group', $fields);
173 FROM civicrm_option_value v
174 INNER JOIN civicrm_option_group g ON v.option_group_id = g.id
175 WHERE g.name IN ( $nameString )
177 $fields = &$this->dbFields('CRM_Core_DAO_OptionValue', TRUE);
178 $this->sql($sql, 'civicrm_option_value', $fields);
183 * @param string $tableName
186 * @param null $additionalWhereCond
188 public function table(
193 $additionalWhereCond = NULL
199 $idString = implode(',', $ids);
204 WHERE $whereField IN ( $idString )
207 if ($additionalWhereCond) {
208 $sql .= " AND $additionalWhereCond";
211 $this->sql($sql, $tableName, $fields);
216 * @param string $tableName
219 public function sql($sql, $tableName, &$fields) {
220 $dao = &CRM_Core_DAO
::executeQuery($sql);
222 while ($dao->fetch()) {
224 foreach ($fields as $name) {
225 if (empty($dao->$name)) {
226 $value[$name] = NULL;
229 $value[$name] = $dao->$name;
232 $this->appendValue($dao->id
, $tableName, $value);
240 public function contact(&$contactIDs) {
241 $fields = &$this->dbFields('CRM_Contact_DAO_Contact', TRUE);
242 $this->table($contactIDs, 'civicrm_contact', $fields, 'id', NULL);
248 public function note(&$contactIDs) {
249 $fields = &$this->dbFields('CRM_Core_DAO_Note', TRUE);
250 $this->table($contactIDs, 'civicrm_note', $fields, 'entity_id', "entity_table = 'civicrm_contact'");
256 public function phone(&$contactIDs) {
257 $fields = &$this->dbFields('CRM_Core_DAO_Phone', TRUE);
258 $this->table($contactIDs, 'civicrm_phone', $fields, 'contact_id', NULL);
264 public function email(&$contactIDs) {
265 $fields = &$this->dbFields('CRM_Core_DAO_Email', TRUE);
266 $this->table($contactIDs, 'civicrm_email', $fields, 'contact_id', NULL);
272 public function im(&$contactIDs) {
273 $fields = &$this->dbFields('CRM_Core_DAO_IM', TRUE);
274 $this->table($contactIDs, 'civicrm_im', $fields, 'contact_id', NULL);
280 public function website(&$contactIDs) {
281 $fields = &$this->dbFields('CRM_Core_DAO_Website', TRUE);
282 $this->table($contactIDs, 'civicrm_website', $fields, 'contact_id', NULL);
288 public function address(&$contactIDs) {
289 $fields = &$this->dbFields('CRM_Core_DAO_Email', TRUE);
290 $this->table($contactIDs, 'civicrm_address', $fields, 'contact_id', NULL);
296 public function groupContact(&$contactIDs) {
297 $fields = &$this->dbFields('CRM_Contact_DAO_GroupContact', TRUE);
298 $this->table($contactIDs, 'civicrm_group_contact', $fields, 'contact_id', NULL);
302 * TODO - support group inheritance
303 * Parent child group ids are encoded in a text string
306 public function group(&$contactIDs) {
307 // handle groups only once
308 static $_groupsHandled = array();
310 $ids = implode(',', $contactIDs);
313 SELECT DISTINCT group_id
314 FROM civicrm_group_contact
315 WHERE contact_id IN ( $ids )
317 $dao = CRM_Core_DAO
::executeQuery($sql);
319 while ($dao->fetch()) {
320 if (!isset($_groupsHandled[$dao->group_id
])) {
321 $groupIDs[] = $dao->group_id
;
322 $_groupsHandled[$dao->group_id
] = 1;
326 $fields = &$this->dbFields('CRM_Contact_DAO_Group', TRUE);
327 $this->table($groupIDs, 'civicrm_group', $fields, 'id');
329 $this->savedSearch($groupIDs);
333 * TODO - support search builder and custom saved searches
336 public function savedSearch(&$groupIDs) {
337 if (empty($groupIDs)) {
341 $idString = implode(",", $groupIDs);
344 FROM civicrm_saved_search s
345 INNER JOIN civicrm_group g on g.saved_search_id = s.id
346 WHERE g.id IN ( $idString )
349 $fields = &$this->dbFields('CRM_Contact_DAO_SavedSearch', TRUE);
350 $this->sql($sql, 'civicrm_saved_search', $fields);
356 public function entityTag(&$contactIDs) {
357 $fields = &$this->dbFields('CRM_Core_DAO_EntityTag', TRUE);
358 $this->table($contactIDs, 'civicrm_entity_tag', $fields, 'entity_id', "entity_table = 'civicrm_contact'");
364 public function tag(&$contactIDs) {
365 // handle tags only once
366 static $_tagsHandled = array();
368 $ids = implode(',', $contactIDs);
371 SELECT DISTINCT tag_id
372 FROM civicrm_entity_tag
373 WHERE entity_id IN ( $ids )
374 AND entity_table = 'civicrm_contact'
376 $dao = CRM_Core_DAO
::executeQuery($sql);
378 while ($dao->fetch()) {
379 if (!isset($_tagsHandled[$dao->tag_id
])) {
380 $tagIDs[] = $dao->tag_id
;
381 $_tagsHandled[$dao->tag_id
] = 1;
385 $fields = &$this->dbFields('CRM_Core_DAO_Tag', TRUE);
386 $this->table($tagIDs, 'civicrm_tag', $fields, 'id');
391 * @param $additionalContacts
393 public function relationship(&$contactIDs, &$additionalContacts) {
394 // handle relationships only once
395 static $_relationshipsHandled = array();
397 $ids = implode(',', $contactIDs);
401 FROM civicrm_relationship r
402 WHERE r.contact_id_a IN ( $ids )
405 FROM civicrm_relationship r
406 WHERE r.contact_id_b IN ( $ids )
410 $fields = $this->dbFields('CRM_Contact_DAO_Relationship', TRUE);
411 $dao = &CRM_Core_DAO
::executeQuery($sql);
412 while ($dao->fetch()) {
413 if (isset($_relationshipsHandled[$dao->id
])) {
416 $_relationshipsHandled[$dao->id
] = $dao->id
;
418 $relationship = array();
419 foreach ($fields as $fld) {
420 if (empty($dao->$fld)) {
421 $relationship[$fld] = NULL;
424 $relationship[$fld] = $dao->$fld;
427 $this->appendValue($dao->id
, 'civicrm_relationship', $relationship);
429 $this->addAdditionalContacts(array(
441 * @param $additionalContacts
443 public function activity(&$contactIDs, &$additionalContacts) {
444 static $_activitiesHandled = array();
445 $activityContacts = CRM_Core_OptionGroup
::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
446 $assigneeID = CRM_Utils_Array
::key('Activity Assignees', $activityContacts);
447 $targetID = CRM_Utils_Array
::key('Activity Targets', $activityContacts);
448 $ids = implode(',', $contactIDs);
450 // query framing returning all contacts in valid activity
452 SELECT a.*, ac.id as acID, ac.activity_id, ac.contact_id, ac.record_type_id
453 FROM civicrm_activity a
454 INNER JOIN civicrm_activity_contact ac ON ac.activity_id = a.id
455 WHERE ac.contact_id IN ( $ids )
456 AND (a.activity_type_id != 3 AND a.activity_type_id != 20)
459 $fields = &$this->dbFields('CRM_Activity_DAO_Activity', TRUE);
461 $dao = &CRM_Core_DAO
::executeQuery($sql);
462 while ($dao->fetch()) {
463 // adding source, target and assignee contacts in additional contacts array
464 $this->addAdditionalContacts(array($dao->contact_id
),
468 // append values of activity contacts
469 $activityContacts = array(
471 'contact_id' => $dao->contact_id
,
472 'activity_id' => $dao->activity_id
,
473 'record_type_id' => $dao->record_type_id
,
475 $this->appendValue($dao->acID
, 'civicrm_activity_contact', $activityContacts);
477 if (isset($_activitiesHandled[$dao->id
])) {
480 $_activitiesHandled[$dao->id
] = $dao->id
;
483 foreach ($fields as $fld) {
484 if (empty($dao->$fld)) {
485 $activity[$fld] = NULL;
488 $activity[$fld] = $dao->$fld;
492 // append activity value
493 $this->appendValue($dao->id
, 'civicrm_activity', $activity);
500 * @param string $name
503 public function appendValue($id, $name, $value) {
508 if (!isset($this->_values
[$name])) {
509 $this->_values
[$name] = array();
510 $this->_values
[$name][] = array_keys($value);
512 $this->_values
[$name][] = array_values($value);
516 * @param string $daoName
517 * @param bool $onlyKeys
521 public function dbFields($daoName, $onlyKeys = FALSE) {
522 static $_fieldsRetrieved = array();
524 if (!isset($_fieldsRetrieved[$daoName])) {
525 $_fieldsRetrieved[$daoName] = array();
526 $daoFile = str_replace('_',
530 include_once $daoFile;
532 $daoFields = &$daoName::fields();
534 foreach ($daoFields as $key => & $value) {
535 $_fieldsRetrieved[$daoName][$value['name']] = array(
536 'uniqueName' => $key,
537 'type' => $value['type'],
538 'title' => CRM_Utils_Array
::value('title', $value, NULL),
544 return array_keys($_fieldsRetrieved[$daoName]);
547 return $_fieldsRetrieved[$daoName];
553 * @param $additionalContacts
555 public function addAdditionalContacts($contactIDs, &$additionalContacts) {
556 if (!$this->_discoverContacts
) {
560 foreach ($contactIDs as $cid) {
562 !isset($this->_allContactIDs
[$cid]) &&
563 !isset($additionalContacts[$cid])
565 $additionalContacts[$cid] = $cid;
573 public function export(&$contactIDs) {
574 $chunks = &$this->splitContactIDs($contactIDs);
576 $additionalContactIDs = array();
578 foreach ($chunks as $chunk) {
579 $this->getValues($chunk, $additionalContactIDs);
582 if (!empty($additionalContactIDs)) {
583 $this->_allContactIDs
= $this->_allContactIDs +
$additionalContactIDs;
584 $this->export($additionalContactIDs);
589 * @param string $fileName
590 * @param null $lastExportTime
591 * @param bool $discoverContacts
595 $lastExportTime = NULL,
596 $discoverContacts = FALSE
598 $this->_discoverContacts
= $discoverContacts;
600 if (!$lastExportTime) {
608 SELECT DISTINCT entity_id
610 WHERE entity_table = 'civicrm_contact'
611 AND modified_date >= $lastExportTime
613 SELECT DISTINCT contact_id
614 FROM civicrm_subscription_history
615 WHERE date >= $lastExportTime
620 $dao = &CRM_Core_DAO
::executeQuery($sql);
622 $contactIDs = array();
623 while ($dao->fetch()) {
624 $contactIDs[$dao->id
] = $dao->id
;
627 $this->_allContactIDs
= $contactIDs;
628 $this->_values
= array();
632 $this->export($contactIDs);
634 $json = json_encode($this->_values
, JSON_NUMERIC_CHECK
);
635 file_put_contents($fileName,
639 // print_r( json_decode( $json ) );