<?php
/*
+--------------------------------------------------------------------+
- | CiviCRM version 4.4 |
+ | CiviCRM version 4.6 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2013 |
+ | Copyright CiviCRM LLC (c) 2004-2014 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
-*/
+ */
/**
*
* @package CRM
- * @copyright CiviCRM LLC (c) 2004-2013
+ * @copyright CiviCRM LLC (c) 2004-2014
* $Id$
*
* add static functions to include some common functionality
class CRM_Core_BAO_Block {
/**
- * Fields that are required for a valid block
+ * Fields that are required for a valid block.
*/
static $requiredBlockFields = array(
'email' => array('email'),
'phone' => array('phone'),
'im' => array('name'),
- 'openid' => array('openid')
+ 'openid' => array('openid'),
);
/**
* Given the list of params in the params array, fetch the object
* and store the values in the values array
*
- * @param Object $block typically a Phone|Email|IM|OpenID object
- * @param string $blockName name of the above object
- * @param array $params input parameters to find object
- * @param array $values output values of the object
+ * @param string $blockName
+ * Name of the above object.
+ * @param array $params
+ * Input parameters to find object.
*
- * @return array of $block objects.
- * @access public
- * @static
+ * @return array
+ * Array of $block objects.
*/
- static function &getValues($blockName, $params) {
+ public static function &getValues($blockName, $params) {
if (empty($params)) {
return NULL;
}
$BAOString = 'CRM_Core_BAO_' . $blockName;
- $block = new $BAOString( );
+ $block = new $BAOString();
$blocks = array();
if (!isset($params['entity_table'])) {
$count = 1;
foreach ($blockIds as $blockId) {
- $block = new $BAOString( );
- $block->id = $blockId['id'];
- $getBlocks = self::retrieveBlock($block, $blockName);
+ $block = new $BAOString();
+ $block->id = $blockId['id'];
+ $getBlocks = self::retrieveBlock($block, $blockName);
$blocks[$count++] = array_pop($getBlocks);
}
}
* Given the list of params in the params array, fetch the object
* and store the values in the values array
*
- * @param Object $block typically a Phone|Email|IM|OpenID object
- * @param string $blockName name of the above object
- * @param array $values output values of the object
+ * @param Object $block
+ * Typically a Phone|Email|IM|OpenID object.
+ * @param string $blockName
+ * Name of the above object.
*
- * @return array of $block objects.
- * @access public
- * @static
+ * @return array
+ * Array of $block objects.
*/
- static function retrieveBlock(&$block, $blockName) {
+ public static function retrieveBlock(&$block, $blockName) {
// we first get the primary location due to the order by clause
$block->orderBy('is_primary desc, id');
$block->find();
}
/**
- * check if the current block object has any valid data
+ * Check if the current block object has any valid data.
*
- * @param array $blockFields array of fields that are of interest for this object
- * @param array $params associated array of submitted fields
+ * @param array $blockFields
+ * Array of fields that are of interest for this object.
+ * @param array $params
+ * Associated array of submitted fields.
*
- * @return boolean true if the block has data, otherwise false
- * @access public
- * @static
+ * @return bool
+ * true if the block has data, otherwise false
*/
- static function dataExists($blockFields, &$params) {
+ public static function dataExists($blockFields, &$params) {
foreach ($blockFields as $field) {
if (CRM_Utils_System::isNull(CRM_Utils_Array::value($field, $params))) {
return FALSE;
}
/**
- * check if the current block exits
+ * Check if the current block exits.
*
- * @param string $blockName bloack name
- * @param array $params associated array of submitted fields
+ * @param string $blockName
+ * Bloack name.
+ * @param array $params
+ * Associated array of submitted fields.
*
- * @return boolean true if the block exits, otherwise false
- * @access public
- * @static
+ * @return bool
+ * true if the block exits, otherwise false
*/
- static function blockExists($blockName, &$params) {
+ public static function blockExists($blockName, &$params) {
// return if no data present
- if (!CRM_Utils_Array::value($blockName, $params) || !is_array($params[$blockName])) {
+ if (empty($params[$blockName]) || !is_array($params[$blockName])) {
return FALSE;
}
}
/**
- * Function to get all block ids for a contact
+ * Get all block ids for a contact.
+ *
+ * @param string $blockName
+ * Block name.
+ * @param int $contactId
+ * Contact id.
*
- * @param string $blockName block name
- * @param int $contactId contact id
+ * @param null $entityElements
+ * @param bool $updateBlankLocInfo
*
- * @return array $contactBlockIds formatted array of block ids
+ * @return array
+ * formatted array of block ids
*
- * @access public
- * @static
*/
- static function getBlockIds($blockName, $contactId = NULL, $entityElements = NULL, $updateBlankLocInfo = FALSE) {
+ public static function getBlockIds($blockName, $contactId = NULL, $entityElements = NULL, $updateBlankLocInfo = FALSE) {
$allBlocks = array();
$name = ucfirst($blockName);
// e.g $bao = new $baoString;
// $bao->getAllBlocks()
$baoFunction = 'all' . $name . 's';
- $allBlocks = $baoString::$baoFunction( $contactId, $updateBlankLocInfo );
+ $allBlocks = $baoString::$baoFunction($contactId, $updateBlankLocInfo);
}
elseif (!empty($entityElements) && $blockName != 'openid') {
$baoFunction = 'allEntity' . $name . 's';
- $allBlocks = $baoString::$baoFunction( $entityElements );
+ $allBlocks = $baoString::$baoFunction($entityElements);
}
return $allBlocks;
}
/**
- * takes an associative array and creates a block
+ * Takes an associative array and creates a block.
*
- * @param string $blockName block name
- * @param array $params (reference ) an assoc array of name/value pairs
- * @param array $requiredFields fields that's are required in a block
+ * @param string $blockName
+ * Block name.
+ * @param array $params
+ * (reference ) an assoc array of name/value pairs.
+ * @param null $entity
+ * @param int $contactId
*
- * @return object CRM_Core_BAO_Block object on success, null otherwise
- * @access public
- * @static
+ * @return object
+ * CRM_Core_BAO_Block object on success, null otherwise
*/
- static function create($blockName, &$params, $entity = NULL, $contactId = NULL) {
+ public static function create($blockName, &$params, $entity = NULL, $contactId = NULL) {
+
if (!self::blockExists($blockName, $params)) {
return NULL;
}
- $name = ucfirst($blockName);
- $contactId = NULL;
- $isPrimary = $isBilling = TRUE;
+ // Set up required information / defaults
$entityElements = $blocks = array();
+ $resetPrimary = $primarySet = $billingSet = FALSE;
+ $contactId = NULL;
+
+ $baoString = 'CRM_Core_BAO_' . ucfirst($blockName);
+ $updateBlankLocInfo = CRM_Utils_Array::value('updateBlankLocInfo', $params, FALSE);
if ($entity) {
$entityElements = array(
$contactId = $params['contact_id'];
}
- $updateBlankLocInfo = CRM_Utils_Array::value('updateBlankLocInfo', $params, FALSE);
+ // Get current and submitted values
+ $existingValues = self::getBlockIds($blockName, $contactId, $entityElements, $updateBlankLocInfo);
+ $submittedValues = $params[$blockName];
- //get existsing block ids.
- $blockIds = self::getBlockIds($blockName, $contactId, $entityElements, $updateBlankLocInfo);
-
- if (!$updateBlankLocInfo) {
- $resetPrimaryId = NULL;
- $primaryId = FALSE;
- foreach ($params[$blockName] as $count => $value) {
- $blockId = CRM_Utils_Array::value('id', $value);
- if ($blockId) {
- if (is_array($blockIds)
- && array_key_exists($blockId, $blockIds)
- ) {
- unset($blockIds[$blockId]);
- }
- else {
- unset($value['id']);
- }
- }
- //lets allow to update primary w/ more cleanly.
- if (!$resetPrimaryId &&
- CRM_Utils_Array::value('is_primary', $value)
- ) {
- $primaryId = TRUE;
- if (is_array($blockIds)) {
- foreach ($blockIds as $blockId => $blockValue) {
- if (CRM_Utils_Array::value('is_primary', $blockValue)) {
- $resetPrimaryId = $blockId;
- break;
- }
- }
- }
- if ($resetPrimaryId) {
- $baoString = 'CRM_Core_BAO_' . $blockName;
- $block = new $baoString( );
+ // For each submitted value
+ foreach ($submittedValues as $count => $submittedValue) {
+
+ // Set the contact ID
+ $submittedValue['contact_id'] = $contactId;
+
+ // If this is a primary value, and we haven't unset a primary value yet, and there are values on the contact
+ // Then unset any primary value currently on the Contact
+ if (!empty($submittedValue['is_primary']) && !$resetPrimary && is_array($existingValues)) {
+ foreach ($existingValues as $existingValueId => $existingValue) {
+ if (!empty($existingValue['is_primary'])) {
+
+ // @todo Can we refactor this?
+ $block = new $baoString();
$block->selectAdd();
$block->selectAdd("id, is_primary");
- $block->id = $resetPrimaryId;
+ $block->id = $existingValue['id'];
if ($block->find(TRUE)) {
$block->is_primary = FALSE;
$block->save();
}
$block->free();
+
+ // Stop looping since we found a match
+ $resetPrimary = TRUE;
+ break;
}
}
}
- }
- foreach ($params[$blockName] as $count => $value) {
- if (!is_array($value)) {
- continue;
+ // If there is already an ID passed in
+ if (!empty($submittedValue['id'])) {
+ // If the ID already exists on the contact
+ // Then we don't want to match on it later, so unset it
+ if (array_key_exists($submittedValue['id'], $existingValues)) {
+ unset($existingValues[$existingValueId]);
+ }
+ // Otherwise it is a new value, so ignore the passed in ID
+ else {
+ unset($submittedValue['id']);
+ }
}
- $contactFields = array(
- 'contact_id' => $contactId,
- 'location_type_id' => CRM_Utils_Array::value('location_type_id', $value),
- );
- //check for update
- if (!CRM_Utils_Array::value('id', $value) &&
- is_array($blockIds) && !empty($blockIds)
- ) {
- foreach ($blockIds as $blockId => $blockValue) {
- if ($updateBlankLocInfo) {
- if (CRM_Utils_Array::value($count, $blockIds)) {
- $value['id'] = $blockIds[$count]['id'];
- unset($blockIds[$count]);
- }
- }
- else {
- if ($blockValue['locationTypeId'] == CRM_Utils_Array::value('location_type_id', $value)) {
- $valueId = FALSE;
-
- if ($blockName == 'phone') {
- $phoneTypeBlockValue = CRM_Utils_Array::value('phoneTypeId', $blockValue);
- if ($phoneTypeBlockValue == CRM_Utils_Array::value('phone_type_id', $value)) {
- $valueId = TRUE;
- }
- }
- elseif ($blockName == 'im') {
- $providerBlockValue = CRM_Utils_Array::value('providerId', $blockValue);
- if ($providerBlockValue == $value['provider_id']) {
- $valueId = TRUE;
- }
+ // Otherwise, if there was no ID passed in
+ // Loop through the current values, and find the first match on location type
+ else {
+ foreach ($existingValues as $existingValueId => $existingValue) {
+ if ($existingValue['locationTypeId'] == $submittedValue['location_type_id']) {
+
+ // Also require a match on 'type id' for phone and IM blocks
+ $matchFound = FALSE;
+
+ if ($blockName == 'phone') {
+ if (CRM_Utils_Array::value('phoneTypeId', $existingValue) == CRM_Utils_Array::value('phone_type_id', $submittedValue)) {
+ $matchFound = TRUE;
}
- else {
- $valueId = TRUE;
+ }
+ elseif ($blockName == 'im') {
+ if (CRM_Utils_Array::value('providerId', $existingValue) == CRM_Utils_Array::value('provider_id', $submittedValue)) {
+ $matchFound = TRUE;
}
+ }
+ else {
+ $matchFound = TRUE;
+ }
- if ($valueId) {
- //assigned id as first come first serve basis
- $value['id'] = $blockValue['id'];
- if (!$primaryId && CRM_Utils_Array::value('is_primary', $blockValue)) {
- $value['is_primary'] = $blockValue['is_primary'];
- }
- unset($blockIds[$blockId]);
- break;
+ // If we found a match
+ if ($matchFound) {
+ // Match up the ID
+ $submittedValue['id'] = $existingValue['id'];
+ // If the submitted value is not primary, but the matched value is
+ // Then set the submitted value to be primary
+ if (empty($submittedValue['is_primary']) && !empty($existingValue['is_primary'])) {
+ $submittedValue['is_primary'] = 1;
}
+ // Remove the original value from the array so we don't match on it again
+ unset($existingValues[$existingValueId]);
+ break;
}
}
}
}
- $dataExits = self::dataExists(self::$requiredBlockFields[$blockName], $value);
+ // Check if data exists in the submitted value
+ $dataExists = self::dataExists(self::$requiredBlockFields[$blockName], $submittedValue);
- // Note there could be cases when block info already exist ($value[id] is set) for a contact/entity
- // BUT info is not present at this time, and therefore we should be really careful when deleting the block.
- // $updateBlankLocInfo will help take appropriate decision. CRM-5969
- if (CRM_Utils_Array::value('id', $value) && !$dataExits && $updateBlankLocInfo) {
- //delete the existing record
- self::blockDelete($blockName, array('id' => $value['id']));
- continue;
- }
- elseif (!$dataExits) {
- continue;
- }
+ // If there is data
+ if ($dataExists) {
- if ($isPrimary && CRM_Utils_Array::value('is_primary', $value)) {
- $contactFields['is_primary'] = $value['is_primary'];
- $isPrimary = FALSE;
- }
- else {
- $contactFields['is_primary'] = 0;
+ // "There can be only one" primary / billing block
+ if (!$primarySet && !empty($submittedValue['is_primary'])) {
+ $submittedValue['is_primary'] = 1;
+ $primarySet = TRUE;
+ }
+ else {
+ $contactFields['is_primary'] = 0;
+ }
+
+ if (!$billingSet && !empty($submittedValue['is_billing'])) {
+ $submittedValue['is_billing'] = 1;
+ $billingSet = TRUE;
+ }
+ else {
+ $contactFields['is_billing'] = 0;
+ }
+
+ // Add the value to the list of blocks
+ $blocks[] = $baoString::add($submittedValue);
}
- if ($isBilling && CRM_Utils_Array::value('is_billing', $value)) {
- $contactFields['is_billing'] = $value['is_billing'];
- $isBilling = FALSE;
+ // Otherwise, if there is no data, and there is an ID, and we are deleting 'blanked' values
+ // Then delete it
+ elseif (!empty($submittedValue['id']) && $updateBlankLocInfo) {
+ self::blockDelete($blockName, array('id' => $submittedValue['id']));
}
+
+ // Otherwise we ignore it
else {
- $contactFields['is_billing'] = 0;
}
- $blockFields = array_merge($value, $contactFields);
- $baoString = 'CRM_Core_BAO_' . $name;
- $blocks[] = $baoString::add( $blockFields );
- }
-
- // we need to delete blocks that were deleted during update
- if ($updateBlankLocInfo && !empty($blockIds)) {
- foreach ($blockIds as $deleteBlock) {
- if (!CRM_Utils_Array::value('id', $deleteBlock)) {
- continue;
- }
- self::blockDelete($blockName, array('id' => $deleteBlock['id']));
- }
}
return $blocks;
}
/**
- * Function to delete block
+ * Delete block.
*
- * @param string $blockName block name
- * @param int $params associates array
+ * @param string $blockName
+ * Block name.
+ * @param int $params
+ * Associates array.
*
* @return void
- * @static
*/
- static function blockDelete($blockName, $params) {
+ public static function blockDelete($blockName, $params) {
$name = ucfirst($blockName);
if ($blockName == 'im') {
$name = 'IM';
}
$baoString = 'CRM_Core_DAO_' . $name;
- $block = new $baoString( );
+ $block = new $baoString();
$block->copyValues($params);
- /*
- * CRM-11006 add call to pre and post hook for delete action
- */
+
+ // CRM-11006 add call to pre and post hook for delete action
CRM_Utils_Hook::pre('delete', $name, $block->id, CRM_Core_DAO::$_nullArray);
$block->delete();
CRM_Utils_Hook::post('delete', $name, $block->id, $block);
* - if no other entry is 1 change to 1
* - if one other entry exists change that to 1
* - if more than one other entry exists change first one to 1
- * @fixme - perhaps should choose by location_type
+ * @fixme - perhaps should choose by location_type
* # empty - same as 0 as once we have checked first step
* we know if it should be 1 or 0
*
* if $params['id'] is set $params['contact_id'] may need to be retrieved
*
- * @param array $params
- * @static
+ * @param array $params
+ * @param $class
+ *
+ * @throws API_Exception
*/
public static function handlePrimary(&$params, $class) {
$table = CRM_Core_DAO_AllCoreTables::getTableForClass($class);
}
// if params is_primary then set all others to not be primary & exit out
- if (CRM_Utils_Array::value('is_primary', $params)) {
+ if (!empty($params['is_primary'])) {
$sql = "UPDATE $table SET is_primary = 0 WHERE contact_id = %1";
$sqlParams = array(1 => array($contactId, 'Integer'));
// we don't want to create unecessary entries in the log_ tables so exclude the one we are working on
- if(!empty($params['id'])){
+ if (!empty($params['id'])) {
$sql .= " AND id <> %2";
$sqlParams[2] = array($params['id'], 'Integer');
}
* is_primary to 1
* CRM-10451
*/
- if ( $existingEntities->N == 1 && $existingEntities->id == CRM_Utils_Array::value( 'id', $params ) ) {
+ if ($existingEntities->N == 1 && $existingEntities->id == CRM_Utils_Array::value('id', $params)) {
$params['is_primary'] = 1;
return;
}
}
/**
- * Sort location array so primary element is first
- * @param Array $location
+ * Sort location array so primary element is first.
+ *
+ * @param array $locations
*/
- static function sortPrimaryFirst(&$locations){
+ public static function sortPrimaryFirst(&$locations) {
uasort($locations, 'self::primaryComparison');
}
-/**
- * compare 2 locations to see which should go first based on is_primary
- * (sort function for sortPrimaryFirst)
- * @param array $location1
- * @param array_type $location2
- * @return number
- */
- static function primaryComparison($location1, $location2){
+ /**
+ * compare 2 locations to see which should go first based on is_primary
+ * (sort function for sortPrimaryFirst)
+ * @param array $location1
+ * @param array $location2
+ * @return int
+ */
+ public static function primaryComparison($location1, $location2) {
$l1 = CRM_Utils_Array::value('is_primary', $location1);
$l2 = CRM_Utils_Array::value('is_primary', $location2);
if ($l1 == $l2) {
}
return ($l1 < $l2) ? -1 : 1;
}
-}
+}