$params['entity_table'], 'entity_id' => $params['entity_id'], ]; $location['id'] = self::createLocBlock($location, $entityElements); } else { // when we come from a form which displays all the location elements (like the edit form or the inline block // elements, we can skip the below check. The below check adds quite a feq queries to an already overloaded // form if (!CRM_Utils_Array::value('updateBlankLocInfo', $params, FALSE)) { // make sure contact should have only one primary block, CRM-5051 self::checkPrimaryBlocks(CRM_Utils_Array::value('contact_id', $params)); } } return $location; } /** * Creates the entry in the civicrm_loc_block. * * @param string $location * @param array $entityElements * * @return int */ public static function createLocBlock(&$location, &$entityElements) { $locId = self::findExisting($entityElements); $locBlock = []; if ($locId) { $locBlock['id'] = $locId; } foreach ([ 'phone', 'email', 'im', 'address', ] as $loc) { $locBlock["{$loc}_id"] = !empty($location["$loc"][0]) ? $location["$loc"][0]->id : NULL; $locBlock["{$loc}_2_id"] = !empty($location["$loc"][1]) ? $location["$loc"][1]->id : NULL; } $countNull = 0; foreach ($locBlock as $key => $block) { if (empty($locBlock[$key])) { $locBlock[$key] = 'null'; $countNull++; } } if (count($locBlock) == $countNull) { // implies nothing is set. return NULL; } $locBlockInfo = self::addLocBlock($locBlock); return $locBlockInfo->id; } /** * Takes an entity array and finds the existing location block. * * @param array $entityElements * * @return int */ public static function findExisting($entityElements) { $eid = $entityElements['entity_id']; $etable = $entityElements['entity_table']; $query = " SELECT e.loc_block_id as locId FROM {$etable} e WHERE e.id = %1"; $params = [1 => [$eid, 'Integer']]; $dao = CRM_Core_DAO::executeQuery($query, $params); while ($dao->fetch()) { $locBlockId = $dao->locId; } return $locBlockId; } /** * Takes an associative array and adds location block. * * @param array $params * (reference ) an assoc array of name/value pairs. * * @return CRM_Core_BAO_locBlock * Object on success, null otherwise */ public static function addLocBlock(&$params) { $locBlock = new CRM_Core_DAO_LocBlock(); $locBlock->copyValues($params); return $locBlock->save(); } /** * Delete the Location Block. * * @param int $locBlockId * Id of the Location Block. */ public static function deleteLocBlock($locBlockId) { if (!$locBlockId) { return; } $locBlock = new CRM_Core_DAO_LocBlock(); $locBlock->id = $locBlockId; $locBlock->find(TRUE); //resolve conflict of having same ids for multiple blocks $store = [ 'IM_1' => $locBlock->im_id, 'IM_2' => $locBlock->im_2_id, 'Email_1' => $locBlock->email_id, 'Email_2' => $locBlock->email_2_id, 'Phone_1' => $locBlock->phone_id, 'Phone_2' => $locBlock->phone_2_id, 'Address_1' => $locBlock->address_id, 'Address_2' => $locBlock->address_2_id, ]; $locBlock->delete(); foreach ($store as $daoName => $id) { if ($id) { $daoName = 'CRM_Core_DAO_' . substr($daoName, 0, -2); $dao = new $daoName(); $dao->id = $id; $dao->find(TRUE); $dao->delete(); } } } /** * Check if there is data to create the object. * * @param array $params * (reference ) an assoc array of name/value pairs. * * @return bool */ public static function dataExists(&$params) { // return if no data present $dataExists = FALSE; foreach (self::$blocks as $block) { if (array_key_exists($block, $params)) { $dataExists = TRUE; break; } } return $dataExists; } /** * Get values. * * @param array $entityBlock * @param bool $microformat * * @return array * array of objects(CRM_Core_BAO_Location) */ public static function &getValues($entityBlock, $microformat = FALSE) { if (empty($entityBlock)) { return NULL; } $blocks = []; $name_map = [ 'im' => 'IM', 'openid' => 'OpenID', ]; $blocks = []; //get all the blocks for this contact foreach (self::$blocks as $block) { if (array_key_exists($block, $name_map)) { $name = $name_map[$block]; } else { $name = ucfirst($block); } $baoString = 'CRM_Core_BAO_' . $name; $blocks[$block] = $baoString::getValues($entityBlock, $microformat); } return $blocks; } /** * Delete all the block associated with the location. * * @param int $contactId * Contact id. * @param int $locationTypeId * Id of the location to delete. */ public static function deleteLocationBlocks($contactId, $locationTypeId) { // ensure that contactId has a value if (empty($contactId) || !CRM_Utils_Rule::positiveInteger($contactId) ) { CRM_Core_Error::fatal(); } if (empty($locationTypeId) || !CRM_Utils_Rule::positiveInteger($locationTypeId) ) { // so we only delete the blocks which DO NOT have a location type Id // CRM-3581 $locationTypeId = 'null'; } static $blocks = ['Address', 'Phone', 'IM', 'OpenID', 'Email']; $params = ['contact_id' => $contactId, 'location_type_id' => $locationTypeId]; foreach ($blocks as $name) { CRM_Core_BAO_Block::blockDelete($name, $params); } } /** * Copy or update location block. * * @param int $locBlockId * Location block id. * @param int $updateLocBlockId * Update location block id. * * @return int * newly created/updated location block id. */ public static function copyLocBlock($locBlockId, $updateLocBlockId = NULL) { CRM_Core_Error::deprecatedFunctionWarning('unused function which will be removed'); //get the location info. $defaults = $updateValues = []; $locBlock = ['id' => $locBlockId]; CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_LocBlock', $locBlock, $defaults); if ($updateLocBlockId) { //get the location info for update. $copyLocationParams = ['id' => $updateLocBlockId]; CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_LocBlock', $copyLocationParams, $updateValues); foreach ($updateValues as $key => $value) { if ($key != 'id') { $copyLocationParams[$key] = 'null'; } } } //copy all location blocks (email, phone, address, etc) foreach ($defaults as $key => $value) { if ($key != 'id') { $tbl = explode("_", $key); $name = ucfirst($tbl[0]); $updateParams = NULL; if ($updateId = CRM_Utils_Array::value($key, $updateValues)) { $updateParams = ['id' => $updateId]; } $copy = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_' . $name, ['id' => $value], $updateParams); $copyLocationParams[$key] = $copy->id; } } $copyLocation = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_LocBlock', ['id' => $locBlock['id']], $copyLocationParams ); return $copyLocation->id; } /** * Make sure contact should have only one primary block, CRM-5051. * * @param int $contactId * Contact id. */ public static function checkPrimaryBlocks($contactId) { if (!$contactId) { return; } // get the loc block ids. $primaryLocBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($contactId, ['is_primary' => 1]); $nonPrimaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($contactId, ['is_primary' => 0]); foreach ([ 'Email', 'IM', 'Phone', 'Address', 'OpenID', ] as $block) { $name = strtolower($block); if (array_key_exists($name, $primaryLocBlockIds) && !CRM_Utils_System::isNull($primaryLocBlockIds[$name]) ) { if (count($primaryLocBlockIds[$name]) > 1) { // keep only single block as primary. $primaryId = array_pop($primaryLocBlockIds[$name]); $resetIds = "(" . implode(',', $primaryLocBlockIds[$name]) . ")"; // reset all primary except one. CRM_Core_DAO::executeQuery("UPDATE civicrm_$name SET is_primary = 0 WHERE id IN $resetIds"); } } elseif (array_key_exists($name, $nonPrimaryBlockIds) && !CRM_Utils_System::isNull($nonPrimaryBlockIds[$name]) ) { // data exists and no primary block - make one primary. CRM_Core_DAO::setFieldValue("CRM_Core_DAO_" . $block, array_pop($nonPrimaryBlockIds[$name]), 'is_primary', 1 ); } } } /** * Get chain select values (whatever that means!). * * @param mixed $values * @param string $valueType * @param bool $flatten * * @return array */ public static function getChainSelectValues($values, $valueType, $flatten = FALSE) { if (!$values) { return []; } $values = array_filter((array) $values); $elements = []; $list = &$elements; $method = $valueType == 'country' ? 'stateProvinceForCountry' : 'countyForState'; foreach ($values as $val) { $result = CRM_Core_PseudoConstant::$method($val); // Format for quickform if ($flatten) { // Option-groups for multiple categories if ($result && count($values) > 1) { $elements["crm_optgroup_$val"] = CRM_Core_PseudoConstant::$valueType($val, FALSE); } $elements += $result; } // Format for js else { // Option-groups for multiple categories if ($result && count($values) > 1) { $elements[] = [ 'value' => CRM_Core_PseudoConstant::$valueType($val, FALSE), 'children' => [], ]; $list = &$elements[count($elements) - 1]['children']; } foreach ($result as $id => $name) { $list[] = [ 'value' => $name, 'key' => $id, ]; } } } return $elements; } }