public static function exportComponents($selectAll, $ids, $params, $order = NULL, $fields = NULL, $moreReturnProperties = NULL, $exportMode = CRM_Export_Form_Select_Relationship::RELATIONSHIP_EXPORT, $componentClause = NULL, $componentTable = NULL, $mergeSameAddress = FALSE, $mergeSameHousehold = FALSE, $exportParams = array(), $queryOperator = 'AND')
 {
     $headerRows = $returnProperties = array();
     $queryMode = CRM_Relationship_BAO_Query::MODE_RELATIONSHIPS;
     //Welke velden exporteren, gezet bij een mapping, indien niet gezet, primary fields.
     if ($fields) {
         foreach ($fields as $key => $value) {
             $fieldName = CRM_Utils_Array::value(0, $value);
             if (!$fieldName) {
                 continue;
             }
             $returnProperties[$fieldName] = 1;
         }
     } else {
         // Copied from CRM_Relationship_BAO_QUERY should be refactored to seperate
         // method.
         $fields = CRM_Contact_BAO_Relationship::fields();
         // Add display_name for both contacts
         $contact_fields = CRM_Contact_BAO_Contact::exportableFields('All', FALSE, TRUE, TRUE);
         $fields['contact_a'] = $contact_fields['display_name'];
         $fields['contact_a']['where'] = 'contact_a.display_name';
         $fields['contact_b'] = $contact_fields['display_name'];
         $fields['contact_b']['where'] = 'contact_b.display_name';
         // Add relationship type field
         $relationship_type_fields = CRM_Contact_BAO_RelationshipType::fields();
         $fields['relationship_type'] = $relationship_type_fields['label_a_b'];
         $fields['relationship_type']['where'] = 'relationship_type.label_a_b';
         // Add custom fields
         $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Relationship'));
         $returnProperties = CRM_Relationship_BAO_Query::defaultReturnProperties();
     }
     if ($moreReturnProperties) {
         $returnProperties = array_merge($returnProperties, $moreReturnProperties);
     }
     $query = new CRM_Relationship_BAO_Query($params, $returnProperties, NULL, FALSE, FALSE, FALSE, TRUE, $queryOperator);
     //sort by state
     //CRM-15301
     $query->_sort = $order;
     list($select, $from, $where, $having) = $query->query();
     $allRelContactArray = $relationQuery = array();
     if (!$selectAll && $componentTable) {
         // TODO For not select all
         //$from .= " INNER JOIN $componentTable ctTable ON ctTable.contact_id = contact_a.id ";
     } elseif ($componentClause) {
         if (empty($where)) {
             $where = "WHERE {$componentClause}";
         } else {
             $where .= " AND {$componentClause}";
         }
     }
     $queryString = "{$select} {$from} {$where} {$having}";
     $groupBy = "";
     if ($queryMode & CRM_Relationship_BAO_Query::MODE_RELATIONSHIPS && $query->_useGroupBy) {
         $groupBy = " GROUP BY relationship.id";
     }
     $queryString .= $groupBy;
     // always add relationship.id to the ORDER clause
     // so the order is deterministic
     if (strpos('relationship.id', $order) === FALSE) {
         $order .= ", relationship.id";
     }
     if ($order) {
         list($field, $dir) = explode(' ', $order, 2);
         $field = trim($field);
         if (!empty($returnProperties[$field])) {
             //CRM-15301
             $queryString .= " ORDER BY {$order}";
         }
     }
     $componentDetails = $headerRows = $sqlColumns = array();
     $setHeader = TRUE;
     $rowCount = self::EXPORT_ROW_COUNT;
     $offset = 0;
     // we write to temp table often to avoid using too much memory
     $tempRowCount = 100;
     $count = -1;
     // for CRM-3157 purposes
     $i18n = CRM_Core_I18n::singleton();
     $outputColumns = array();
     //@todo - it would be clearer to start defining output columns earlier in this function rather than stick with return properties until this point
     // as the array is not actually 'returnProperties' after the sql query is formed - making the alterations to it confusing
     foreach ($returnProperties as $key => $value) {
         $outputColumns[$key] = $value;
     }
     while (1) {
         $limitQuery = "{$queryString} LIMIT {$offset}, {$rowCount}";
         $dao = CRM_Core_DAO::executeQuery($limitQuery);
         if ($dao->N <= 0) {
             break;
         }
         while ($dao->fetch()) {
             $count++;
             $row = array();
             //convert the pseudo constants
             // CRM-14398 there is problem in this architecture that is not easily solved. For now we are using the cloned
             // temporary iterationDAO object to get around it.
             // the issue is that the convertToPseudoNames function is adding additional properties (e.g for campaign) to the DAO object
             // these additional properties are NOT reset when the $dao cycles through the while loop
             // nor are they overwritten as they are not in the loop
             // the convertToPseudoNames will not adequately over-write them either as it doesn't 'kick-in' unless the
             // relevant property is set.
             // It may be that a long-term fix could be introduced there - however, it's probably necessary to figure out how to test the
             // export class before tackling a better architectural fix
             $iterationDAO = clone $dao;
             //first loop through output columns so that we return what is required, and in same order.
             foreach ($outputColumns as $field => $value) {
                 //we should set header only once
                 if ($setHeader) {
                     $sqlDone = FALSE;
                     $headerRows[] = $query->_fields[$field]['title'];
                     if (!$sqlDone) {
                         self::sqlColumnDefn($query, $sqlColumns, $field);
                     }
                 }
                 //build row values (data)
                 $fieldValue = NULL;
                 if (property_exists($iterationDAO, $field)) {
                     $fieldValue = $iterationDAO->{$field};
                 }
                 if ($field == 'id') {
                     $row[$field] = $iterationDAO->relationship_id;
                 } elseif (isset($fieldValue) && $fieldValue != '') {
                     //check for custom data
                     if ($cfID = CRM_Core_BAO_CustomField::getKeyID($field)) {
                         $row[$field] = CRM_Core_BAO_CustomField::getDisplayValue($fieldValue, $cfID, $query->_options);
                     } else {
                         //normal fields with a touch of CRM-3157
                         $row[$field] = $fieldValue;
                     }
                 } else {
                     // if field is empty or null
                     $row[$field] = '';
                 }
             }
             if ($setHeader) {
                 $exportTempTable = self::createTempTable($sqlColumns);
             }
             //build header only once
             $setHeader = FALSE;
             // add component info
             // write the row to a file
             $componentDetails[] = $row;
             // output every $tempRowCount rows
             if ($count % $tempRowCount == 0) {
                 self::writeDetailsToTable($exportTempTable, $componentDetails, $sqlColumns);
                 $componentDetails = array();
             }
         }
         $dao->free();
         $offset += $rowCount;
     }
     if ($exportTempTable) {
         self::writeDetailsToTable($exportTempTable, $componentDetails, $sqlColumns);
         // do merge same address and merge same household processing
         if ($mergeSameAddress) {
             self::mergeSameAddress($exportTempTable, $headerRows, $sqlColumns, $exportParams);
         }
         // merge the records if they have corresponding households
         if ($mergeSameHousehold) {
             self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyMOH);
             self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyHOH);
         }
         // call export hook
         CRM_Utils_Hook::export($exportTempTable, $headerRows, $sqlColumns, $exportMode);
         // now write the CSV file
         self::writeCSVFromTable($exportTempTable, $headerRows, $sqlColumns, $exportMode);
         // delete the export temp table and component table
         $sql = "DROP TABLE IF EXISTS {$exportTempTable}";
         CRM_Core_DAO::executeQuery($sql);
         CRM_Utils_System::civiExit();
     } else {
         CRM_Core_Error::fatal(ts('No records to export'));
     }
 }
 /**
  * Class constructor which also does all the work.
  *
  * @param array $params
  * @param array $returnProperties
  * @param array $fields
  * @param bool $includeRelationshipIds
  * @param bool $strict
  *
  * @param bool $skipPermission
  * @param string $operator
  *
  * @return \CRM_Relationship_BAO_Query
  */
 public function __construct($params = NULL, $returnProperties = NULL, $fields = NULL, $includeRelationshipIds = FALSE, $strict = FALSE, $mode = 1, $skipPermission = FALSE, $operator = 'AND')
 {
     $this->_params =& $params;
     if ($this->_params == NULL) {
         $this->_params = array();
     }
     if (empty($returnProperties)) {
         $this->_returnProperties = self::defaultReturnProperties($mode);
     } else {
         $this->_returnProperties =& $returnProperties;
     }
     $this->_includeRelationshipIds = $includeRelationshipIds;
     $this->_strict = $strict;
     $this->_mode = $mode;
     $this->_skipPermission = $skipPermission;
     //$this->setOperator($operator);
     if ($fields) {
         $this->_fields =& $fields;
         $this->_search = FALSE;
         $this->_skipPermission = TRUE;
     } else {
         $this->_fields = CRM_Contact_BAO_Relationship::fields();
         foreach ($this->_fields as $defaultFieldKey => $defaultField) {
             $this->_fields[$defaultFieldKey]['where'] = 'relationship.' . $defaultFieldKey;
         }
         // Add display_name for both contacts
         $contact_fields = CRM_Contact_BAO_Contact::exportableFields('All', FALSE, TRUE, TRUE);
         $this->_fields['contact_a'] = $contact_fields['display_name'];
         $this->_fields['contact_a']['where'] = 'contact_a.display_name';
         $this->_fields['contact_b'] = $contact_fields['display_name'];
         $this->_fields['contact_b']['where'] = 'contact_b.display_name';
         // Add relationship type field
         $relationship_type_fields = CRM_Contact_BAO_RelationshipType::fields();
         $this->_fields['relationship_type'] = $relationship_type_fields['label_a_b'];
         $this->_fields['relationship_type']['where'] = 'relationship_type.label_a_b';
         // Add custom fields
         $this->_fields = array_merge($this->_fields, CRM_Core_BAO_CustomField::getFieldsForImport('Relationship'));
     }
     // basically do all the work once, and then reuse it
     $this->initialize();
 }
 /**
  * Build the mapping form.
  *
  * @param CRM_Core_Form $form
  * @param string $mappingType
  *   (Export/Import/Search Builder).
  * @param int $mappingId
  * @param int $columnNo
  * @param int $blockCount
  *   (no of blocks shown).
  * @param NULL $exportMode
  *
  * @return void
  */
 public static function buildMappingForm(&$form, $mappingType = 'Export', $mappingId = NULL, $columnNo, $blockCount = 3, $exportMode = NULL)
 {
     $name = "Map";
     $columnCount = array('1' => $columnNo);
     $form->applyFilter('saveMappingName', 'trim');
     //to save the current mappings
     if (!isset($mappingId)) {
         $saveDetailsName = ts('Save this field mapping');
         $form->add('text', 'saveMappingName', ts('Name'));
         $form->add('text', 'saveMappingDesc', ts('Description'));
     } else {
         $form->assign('loadedMapping', $mappingId);
         $params = array('id' => $mappingId);
         $temp = array();
         $mappingDetails = CRM_Core_BAO_Mapping::retrieve($params, $temp);
         $form->assign('savedName', $mappingDetails->name);
         $form->add('hidden', 'mappingId', $mappingId);
         $form->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
         $saveDetailsName = ts('Save as a new field mapping');
         $form->add('text', 'saveMappingName', ts('Name'));
         $form->add('text', 'saveMappingDesc', ts('Description'));
     }
     $form->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, array('onclick' => "showSaveDetails(this)"));
     $form->addFormRule(array('CRM_Export_Form_Map', 'formRule'), $form->get('mappingTypeId'));
     $defaults = array();
     $hasLocationTypes = array();
     $hasRelationTypes = array();
     $fields = array();
     if ($mappingType == 'Export') {
         $required = TRUE;
     }
     $fields = CRM_Contact_BAO_Relationship::fields();
     // add custom fields
     $fields = array_merge($fields, CRM_Core_BAO_CustomField::getFieldsForImport('Relationship'));
     ksort($fields);
     // add component fields
     $compArray = array();
     foreach ($fields as $key => $value) {
         //CRM-2676, replacing the conflict for same custom field name from different custom group.
         $customGroupName = self::getCustomGroupName($key);
         if ($customGroupName) {
             $relatedMapperFields[$key] = $mapperFields[$key] = $customGroupName . ': ' . $value['title'];
         } else {
             $relatedMapperFields[$key] = $mapperFields[$key] = $value['title'];
         }
     }
     $mapperKeys = array_keys($mapperFields);
     $sel1 = array('' => ts('- select field -')) + $mapperFields;
     if (isset($mappingId)) {
         $colCnt = 0;
         list($mappingName, $mappingContactType, $mappingLocation, $mappingPhoneType, $mappingImProvider, $mappingRelation, $mappingOperator, $mappingValue) = CRM_Core_BAO_Mapping::getMappingFields($mappingId);
         $blkCnt = count($mappingName);
         if ($blkCnt >= $blockCount) {
             $blockCount = $blkCnt + 1;
         }
         for ($x = 1; $x < $blockCount; $x++) {
             if (isset($mappingName[$x])) {
                 $colCnt = count($mappingName[$x]);
                 if ($colCnt >= $columnCount[$x]) {
                     $columnCount[$x] = $colCnt;
                 }
             }
         }
     }
     $form->_blockCount = $blockCount;
     $form->_columnCount = $columnCount;
     $form->set('blockCount', $form->_blockCount);
     $form->set('columnCount', $form->_columnCount);
     $defaults = $noneArray = $nullArray = array();
     //used to warn for mismatch column count or mismatch mapping
     $warning = 0;
     for ($x = 1; $x < $blockCount; $x++) {
         for ($i = 0; $i < $columnCount[$x]; $i++) {
             $sel =& $form->addElement('hierselect', "mapper[{$x}][{$i}]", ts('Mapper for Field %1', array(1 => $i)), NULL);
             $jsSet = FALSE;
             if (isset($mappingId)) {
                 //TODO opgeslagen mappings
             }
             //Fix for Export
             $j = 7;
             $formValues = $form->exportValues();
             if (!$jsSet) {
                 if (empty($formValues)) {
                     // Incremented length for third select box(relationship type)
                     for ($k = 1; $k < $j; $k++) {
                         $noneArray[] = array($x, $i, $k);
                     }
                 } else {
                     if (!empty($formValues['mapper'][$x])) {
                         foreach ($formValues['mapper'][$x] as $value) {
                             for ($k = 1; $k < $j; $k++) {
                                 if (!isset($formValues['mapper'][$x][$i][$k]) || !$formValues['mapper'][$x][$i][$k]) {
                                     $noneArray[] = array($x, $i, $k);
                                 } else {
                                     $nullArray[] = array($x, $i, $k);
                                 }
                             }
                         }
                     } else {
                         for ($k = 1; $k < $j; $k++) {
                             $noneArray[] = array($x, $i, $k);
                         }
                     }
                 }
             }
             //Fix for Export
             $sel->setOptions(array($sel1));
         }
         $title = ts('Select more fields');
         $form->addElement('submit', "addMore[{$x}]", $title, array('class' => 'submit-link'));
     }
     //end of block for
     $js = "<script type='text/javascript'>\n";
     $formName = "document.{$name}";
     if (!empty($nullArray)) {
         $js .= "var nullArray = [";
         $elements = array();
         $seen = array();
         foreach ($nullArray as $element) {
             $key = "{$element[0]}, {$element[1]}, {$element[2]}";
             if (!isset($seen[$key])) {
                 $elements[] = "[{$key}]";
                 $seen[$key] = 1;
             }
         }
         $js .= implode(', ', $elements);
         $js .= "]";
         $js .= "\n                for (var i=0;i<nullArray.length;i++) {\n                    if ( {$formName}['mapper['+nullArray[i][0]+']['+nullArray[i][1]+']['+nullArray[i][2]+']'] ) {\n                        {$formName}['mapper['+nullArray[i][0]+']['+nullArray[i][1]+']['+nullArray[i][2]+']'].style.display = '';\n                    }\n                }\n";
     }
     if (!empty($noneArray)) {
         $js .= "var noneArray = [";
         $elements = array();
         $seen = array();
         foreach ($noneArray as $element) {
             $key = "{$element[0]}, {$element[1]}, {$element[2]}";
             if (!isset($seen[$key])) {
                 $elements[] = "[{$key}]";
                 $seen[$key] = 1;
             }
         }
         $js .= implode(', ', $elements);
         $js .= "]";
         $js .= "\n                for (var i=0;i<noneArray.length;i++) {\n                    if ( {$formName}['mapper['+noneArray[i][0]+']['+noneArray[i][1]+']['+noneArray[i][2]+']'] ) {\n  {$formName}['mapper['+noneArray[i][0]+']['+noneArray[i][1]+']['+noneArray[i][2]+']'].style.display = 'none';\n                    }\n                }\n";
     }
     $js .= "</script>\n";
     $form->assign('initHideBoxes', $js);
     $form->assign('columnCount', $columnCount);
     $form->assign('blockCount', $blockCount);
     $form->setDefaults($defaults);
     $form->setDefaultAction('refresh');
 }