public function &returnProperties() { return CRM_Core_BAO_Mapping::returnProperties($this->_formValues); }
/** * Load the smart group cache for a saved search. * * @param object $group * The smart group that needs to be loaded. * @param bool $force * Should we force a search through. */ public static function load(&$group, $force = FALSE) { $groupID = $group->id; $savedSearchID = $group->saved_search_id; if (array_key_exists($groupID, self::$_alreadyLoaded) && !$force) { return; } // grab a lock so other processes don't compete and do the same query $lock = Civi::lockManager()->acquire("data.core.group.{$groupID}"); if (!$lock->isAcquired()) { // this can cause inconsistent results since we don't know if the other process // will fill up the cache before our calling routine needs it. // however this routine does not return the status either, so basically // its a "lets return and hope for the best" return; } self::$_alreadyLoaded[$groupID] = 1; // we now have the lock, but some other process could have actually done the work // before we got here, so before we do any work, lets ensure that work needs to be // done // we allow hidden groups here since we dont know if the caller wants to evaluate an // hidden group if (!$force && !self::shouldGroupBeRefreshed($groupID, TRUE)) { $lock->release(); return; } $sql = NULL; $idName = 'id'; $customClass = NULL; if ($savedSearchID) { $ssParams = CRM_Contact_BAO_SavedSearch::getSearchParams($savedSearchID); // rectify params to what proximity search expects if there is a value for prox_distance // CRM-7021 if (!empty($ssParams)) { CRM_Contact_BAO_ProximityQuery::fixInputParams($ssParams); } $returnProperties = array(); if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $savedSearchID, 'mapping_id')) { $fv = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); $returnProperties = CRM_Core_BAO_Mapping::returnProperties($fv); } if (isset($ssParams['customSearchID'])) { // if custom search // we split it up and store custom class // so temp tables are not destroyed if they are used // hence customClass is defined above at top of function $customClass = CRM_Contact_BAO_SearchCustom::customClass($ssParams['customSearchID'], $savedSearchID); $searchSQL = $customClass->contactIDs(); $searchSQL = str_replace('ORDER BY contact_a.id ASC', '', $searchSQL); if (!strstr($searchSQL, 'WHERE')) { $searchSQL .= " WHERE ( 1 ) "; } $idName = 'contact_id'; } else { $formValues = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); // CRM-17075 using the formValues in this way imposes extra logic and complexity. // we have the where_clause and where tables stored in the saved_search table // and should use these rather than re-processing the form criteria (which over-works // the link between the form layer & the query layer too). // It's hard to think of when you would want to use anything other than return // properties = array('contact_id' => 1) here as the point would appear to be to // generate the list of contact ids in the group. // @todo review this to use values in saved_search table (preferably for 4.8). $query = new CRM_Contact_BAO_Query($ssParams, $returnProperties, NULL, FALSE, FALSE, 1, TRUE, TRUE, FALSE, CRM_Utils_Array::value('display_relationship_type', $formValues), CRM_Utils_Array::value('operator', $formValues, 'AND')); $query->_useDistinct = FALSE; $query->_useGroupBy = FALSE; $searchSQL = $query->searchQuery(0, 0, NULL, FALSE, FALSE, FALSE, TRUE, TRUE, NULL, NULL, NULL, TRUE); } $groupID = CRM_Utils_Type::escape($groupID, 'Integer'); $sql = $searchSQL . " AND contact_a.id NOT IN (\n SELECT contact_id FROM civicrm_group_contact\n WHERE civicrm_group_contact.status = 'Removed'\n AND civicrm_group_contact.group_id = {$groupID} ) "; } if ($sql) { $sql = preg_replace("/^\\s*SELECT/", "SELECT {$groupID} as group_id, ", $sql); } // lets also store the records that are explicitly added to the group // this allows us to skip the group contact LEFT JOIN $sqlB = "\nSELECT {$groupID} as group_id, contact_id as {$idName}\nFROM civicrm_group_contact\nWHERE civicrm_group_contact.status = 'Added'\n AND civicrm_group_contact.group_id = {$groupID} "; $groupIDs = array($groupID); self::remove($groupIDs); $processed = FALSE; $tempTable = 'civicrm_temp_group_contact_cache' . rand(0, 2000); foreach (array($sql, $sqlB) as $selectSql) { if (!$selectSql) { continue; } $insertSql = "CREATE TEMPORARY TABLE {$tempTable} ({$selectSql});"; $processed = TRUE; CRM_Core_DAO::executeQuery($insertSql); CRM_Core_DAO::executeQuery("INSERT IGNORE INTO civicrm_group_contact_cache (contact_id, group_id)\n SELECT DISTINCT {$idName}, group_id FROM {$tempTable}\n "); CRM_Core_DAO::executeQuery(" DROP TEMPORARY TABLE {$tempTable}"); } self::updateCacheTime($groupIDs, $processed); if ($group->children) { //Store a list of contacts who are removed from the parent group $sql = "\nSELECT contact_id\nFROM civicrm_group_contact\nWHERE civicrm_group_contact.status = 'Removed'\nAND civicrm_group_contact.group_id = {$groupID} "; $dao = CRM_Core_DAO::executeQuery($sql); $removed_contacts = array(); while ($dao->fetch()) { $removed_contacts[] = $dao->contact_id; } $childrenIDs = explode(',', $group->children); foreach ($childrenIDs as $childID) { $contactIDs = CRM_Contact_BAO_Group::getMember($childID, FALSE); //Unset each contact that is removed from the parent group foreach ($removed_contacts as $removed_contact) { unset($contactIDs[$removed_contact]); } $values = array(); foreach ($contactIDs as $contactID => $dontCare) { $values[] = "({$groupID},{$contactID})"; } self::store($groupIDs, $values); } } $lock->release(); }
static function preProcessCommon(&$form, $useTable = false) { $form->_contactIds = array(); $form->_contactTypes = array(); // get the submitted values of the search form // we'll need to get fv from either search or adv search in the future $fragment = 'search'; if ($form->_action == CRM_Core_Action::ADVANCED) { $values = $form->controller->exportValues('Advanced'); $fragment .= '/advanced'; } else { if ($form->_action == CRM_Core_Action::PROFILE) { $values = $form->controller->exportValues('Builder'); $fragment .= '/builder'; } else { if ($form->_action == CRM_Core_Action::COPY) { $values = $form->controller->exportValues('Custom'); $fragment .= '/custom'; } else { $values = $form->controller->exportValues('Basic'); } } } //set the user context for redirection of task actions $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $form); require_once 'CRM/Utils/Rule.php'; $urlParams = 'force=1'; if (CRM_Utils_Rule::qfKey($qfKey)) { $urlParams .= "&qfKey={$qfKey}"; } $url = CRM_Utils_System::url('civicrm/contact/' . $fragment, $urlParams); $session = CRM_Core_Session::singleton(); $session->replaceUserContext($url); require_once 'CRM/Contact/Task.php'; $form->_task = CRM_Utils_Array::value('task', $values); $crmContactTaskTasks = CRM_Contact_Task::taskTitles(); $form->assign('taskName', CRM_Utils_Array::value($form->_task, $crmContactTaskTasks)); if ($useTable) { $form->_componentTable = CRM_Core_DAO::createTempTableName('civicrm_task_action', false); $sql = " DROP TABLE IF EXISTS {$form->_componentTable}"; CRM_Core_DAO::executeQuery($sql); $sql = "CREATE TABLE {$form->_componentTable} ( contact_id int primary key) ENGINE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci"; CRM_Core_DAO::executeQuery($sql); } // all contacts or action = save a search if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_all' || $form->_task == CRM_Contact_Task::SAVE_SEARCH) { // need to perform action on all contacts // fire the query again and get the contact id's + display name $sortID = null; if ($form->get(CRM_Utils_Sort::SORT_ID)) { $sortID = CRM_Utils_Sort::sortIDValue($form->get(CRM_Utils_Sort::SORT_ID), $form->get(CRM_Utils_Sort::SORT_DIRECTION)); } $selectorName = $form->controller->selectorName(); require_once str_replace('_', DIRECTORY_SEPARATOR, $selectorName) . '.php'; $fv = $form->get('formValues'); $customClass = $form->get('customSearchClass'); require_once "CRM/Core/BAO/Mapping.php"; $returnProperties = CRM_Core_BAO_Mapping::returnProperties($values); eval('$selector = new ' . $selectorName . '( $customClass, $fv, null, $returnProperties ); '); $params = $form->get('queryParams'); // fix for CRM-5165 $sortByCharacter = $form->get('sortByCharacter'); if ($sortByCharacter && $sortByCharacter != 1) { $params[] = array('sortByCharacter', '=', $sortByCharacter, 0, 0); } $dao =& $selector->contactIDQuery($params, $form->_action, $sortID); $form->_contactIds = array(); if ($useTable) { $count = 0; $insertString = array(); while ($dao->fetch()) { $count++; $insertString[] = " ( {$dao->contact_id} ) "; if ($count % 200 == 0) { $string = implode(',', $insertString); $sql = "REPLACE INTO {$form->_componentTable} ( contact_id ) VALUES {$string}"; CRM_Core_DAO::executeQuery($sql); $insertString = array(); } } if (!empty($insertString)) { $string = implode(',', $insertString); $sql = "REPLACE INTO {$form->_componentTable} ( contact_id ) VALUES {$string}"; CRM_Core_DAO::executeQuery($sql); } $dao->free(); } else { // filter duplicates here // CRM-7058 // might be better to do this in the query, but that logic is a bit complex // and it decides when to use distinct based on input criteria, which needs // to be fixed and optimized. $alreadySeen = array(); while ($dao->fetch()) { if (!array_key_exists($dao->contact_id, $alreadySeen)) { $form->_contactIds[] = $dao->contact_id; $alreadySeen[$dao->contact_id] = 1; } } unset($alreadySeen); $dao->free(); } } else { if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_sel') { // selected contacts only // need to perform action on only selected contacts $insertString = array(); foreach ($values as $name => $value) { if (substr($name, 0, CRM_Core_Form::CB_PREFIX_LEN) == CRM_Core_Form::CB_PREFIX) { $contactID = substr($name, CRM_Core_Form::CB_PREFIX_LEN); if ($useTable) { $insertString[] = " ( {$contactID} ) "; } else { $form->_contactIds[] = substr($name, CRM_Core_Form::CB_PREFIX_LEN); } } } if (!empty($insertString)) { $string = implode(',', $insertString); $sql = "REPLACE INTO {$form->_componentTable} ( contact_id ) VALUES {$string}"; CRM_Core_DAO::executeQuery($sql); } } } //contact type for pick up profiles as per selected contact types with subtypes //CRM-5521 if ($selectedTypes = CRM_Utils_Array::value('contact_type', $values)) { if (!is_array($selectedTypes)) { $selectedTypes = explode(" ", $selectedTypes); } foreach ($selectedTypes as $ct => $dontcare) { if (strpos($ct, CRM_Core_DAO::VALUE_SEPARATOR) === false) { $form->_contactTypes[] = $ct; } else { $separator = strpos($ct, CRM_Core_DAO::VALUE_SEPARATOR); $form->_contactTypes[] = substr($ct, $separator + 1); } } } if (!empty($form->_contactIds)) { $form->_componentClause = ' contact_a.id IN ( ' . implode(',', $form->_contactIds) . ' ) '; $form->assign('totalSelectedContacts', count($form->_contactIds)); $form->_componentIds = $form->_contactIds; } }
/** * Get the contact id for custom search. * * we are not using prev/next table in case of custom search */ public function getContactIds() { // need to perform action on all contacts // fire the query again and get the contact id's + display name $sortID = NULL; if ($this->get(CRM_Utils_Sort::SORT_ID)) { $sortID = CRM_Utils_Sort::sortIDValue($this->get(CRM_Utils_Sort::SORT_ID), $this->get(CRM_Utils_Sort::SORT_DIRECTION)); } $selectorName = $this->controller->selectorName(); require_once str_replace('_', DIRECTORY_SEPARATOR, $selectorName) . '.php'; $fv = $this->get('formValues'); $customClass = $this->get('customSearchClass'); require_once 'CRM/Core/BAO/Mapping.php'; $returnProperties = CRM_Core_BAO_Mapping::returnProperties(self::$_searchFormValues); $selector = new $selectorName($customClass, $fv, NULL, $returnProperties); $params = $this->get('queryParams'); // fix for CRM-5165 $sortByCharacter = $this->get('sortByCharacter'); if ($sortByCharacter && $sortByCharacter != 1) { $params[] = array('sortByCharacter', '=', $sortByCharacter, 0, 0); } $queryOperator = $this->get('queryOperator'); if (!$queryOperator) { $queryOperator = 'AND'; } $dao = $selector->contactIDQuery($params, $this->_action, $sortID, CRM_Utils_Array::value('display_relationship_type', $fv), $queryOperator); $contactIds = array(); while ($dao->fetch()) { $contactIds[$dao->contact_id] = $dao->contact_id; } return $contactIds; }
/** * load the smart group cache for a saved search */ static function load(&$group) { $groupID = $group->id; $savedSearchID = $group->saved_search_id; $sql = null; $idName = 'id'; $customClass = null; if ($savedSearchID) { require_once 'CRM/Contact/BAO/SavedSearch.php'; $ssParams =& CRM_Contact_BAO_SavedSearch::getSearchParams($savedSearchID); $returnProperties = array(); if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $savedSearchID, 'mapping_id')) { require_once "CRM/Core/BAO/Mapping.php"; $fv =& CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); $returnProperties = CRM_Core_BAO_Mapping::returnProperties($fv); } if (isset($ssParams['customSearchID'])) { // if custom search require_once 'CRM/Contact/BAO/SearchCustom.php'; // we split it up and store custom class // so temp tables are not destroyed if they are used // hence customClass is defined above at top of function $customClass = CRM_Contact_BAO_SearchCustom::customClass($ssParams['customSearchID'], $savedSearchID); $searchSQL = $customClass->contactIDs(); $idName = 'contact_id'; } else { require_once 'CRM/Contact/BAO/Query.php'; $query = new CRM_Contact_BAO_Query($ssParams, $returnProperties, null, false, false, 1, true, true, false); $query->_useGroupBy = false; $searchSQL =& $query->searchQuery(0, 0, null, false, false, false, true, true, null); } $groupID = CRM_Utils_Type::escape($groupID, 'Integer'); $sql = $searchSQL . " AND contact_a.id NOT IN ( \n SELECT contact_id FROM civicrm_group_contact \n WHERE civicrm_group_contact.status = 'Removed' \n AND civicrm_group_contact.group_id = {$groupID} ) "; } if ($sql) { $sql .= " UNION "; } // lets also store the records that are explicitly added to the group // this allows us to skip the group contact LEFT JOIN $sql .= "\nSELECT contact_id as {$idName}\nFROM civicrm_group_contact\nWHERE civicrm_group_contact.status = 'Added'\n AND civicrm_group_contact.group_id = {$groupID} "; $dao = CRM_Core_DAO::executeQuery($sql); $values = array(); while ($dao->fetch()) { $values[] = "({$groupID},{$dao->{$idName}})"; } $groupIDs = array($groupID); self::remove($groupIDs); self::store($groupIDs, $values); if ($group->children) { require_once 'CRM/Contact/BAO/Group.php'; $childrenIDs = explode(',', $group->children); foreach ($childrenIDs as $childID) { $contactIDs =& CRM_Contact_BAO_Group::getMember($childID, false); $values = array(); foreach ($contactIDs as $contactID => $dontCare) { $values[] = "({$groupID},{$contactID})"; } self::store($groupIDs, $values); } } }
/** * load the smart group cache for a saved search */ static function load(&$group, $fresh = FALSE) { $groupID = $group->id; $savedSearchID = $group->saved_search_id; if (array_key_exists($groupID, self::$_alreadyLoaded) && !$fresh) { return; } self::$_alreadyLoaded[$groupID] = 1; $sql = NULL; $idName = 'id'; $customClass = NULL; if ($savedSearchID) { $ssParams = CRM_Contact_BAO_SavedSearch::getSearchParams($savedSearchID); // rectify params to what proximity search expects if there is a value for prox_distance // CRM-7021 if (!empty($ssParams)) { CRM_Contact_BAO_ProximityQuery::fixInputParams($ssParams); } $returnProperties = array(); if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $savedSearchID, 'mapping_id')) { $fv = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); $returnProperties = CRM_Core_BAO_Mapping::returnProperties($fv); } if (isset($ssParams['customSearchID'])) { // if custom search // we split it up and store custom class // so temp tables are not destroyed if they are used // hence customClass is defined above at top of function $customClass = CRM_Contact_BAO_SearchCustom::customClass($ssParams['customSearchID'], $savedSearchID); $searchSQL = $customClass->contactIDs(); $idName = 'contact_id'; } else { $formValues = CRM_Contact_BAO_SavedSearch::getFormValues($savedSearchID); $query = new CRM_Contact_BAO_Query($ssParams, $returnProperties, NULL, FALSE, FALSE, 1, TRUE, TRUE, FALSE, CRM_Utils_Array::value('display_relationship_type', $formValues), CRM_Utils_Array::value('operator', $formValues, 'AND')); $query->_useDistinct = FALSE; $query->_useGroupBy = FALSE; $searchSQL = $query->searchQuery(0, 0, NULL, FALSE, FALSE, FALSE, TRUE, TRUE, NULL, NULL, NULL, TRUE); } $groupID = CRM_Utils_Type::escape($groupID, 'Integer'); $sql = $searchSQL . " AND contact_a.id NOT IN (\n SELECT contact_id FROM civicrm_group_contact\n WHERE civicrm_group_contact.status = 'Removed'\n AND civicrm_group_contact.group_id = {$groupID} ) "; } if ($sql) { $sql = preg_replace("/^\\s*SELECT/", "SELECT {$groupID} as group_id, ", $sql); } // lets also store the records that are explicitly added to the group // this allows us to skip the group contact LEFT JOIN $sqlB = "\nSELECT {$groupID} as group_id, contact_id as {$idName}\nFROM civicrm_group_contact\nWHERE civicrm_group_contact.status = 'Added'\n AND civicrm_group_contact.group_id = {$groupID} "; $groupIDs = array($groupID); self::remove($groupIDs); foreach (array($sql, $sqlB) as $selectSql) { if (!$selectSql) { continue; } $insertSql = "INSERT IGNORE INTO civicrm_group_contact_cache (group_id,contact_id) ({$selectSql});"; $processed = TRUE; // FIXME $result = CRM_Core_DAO::executeQuery($insertSql); } self::updateCacheTime($groupIDs, $processed); if ($group->children) { //Store a list of contacts who are removed from the parent group $sql = "\nSELECT contact_id\nFROM civicrm_group_contact\nWHERE civicrm_group_contact.status = 'Removed'\nAND civicrm_group_contact.group_id = {$groupID} "; $dao = CRM_Core_DAO::executeQuery($sql); $removed_contacts = array(); while ($dao->fetch()) { $removed_contacts[] = $dao->contact_id; } $childrenIDs = explode(',', $group->children); foreach ($childrenIDs as $childID) { $contactIDs = CRM_Contact_BAO_Group::getMember($childID, FALSE); //Unset each contact that is removed from the parent group foreach ($removed_contacts as $removed_contact) { unset($contactIDs[$removed_contact]); } $values = array(); foreach ($contactIDs as $contactID => $dontCare) { $values[] = "({$groupID},{$contactID})"; } self::store($groupIDs, $values); } } }
/** * build all the data structures needed to build the form * * @param * @return void * @access public */ function preProcess() { $this->_contactIds = array(); $this->_contactTypes = array(); // get the submitted values of the search form // we'll need to get fv from either search or adv search in the future $fragment = 'search'; if ($this->_action == CRM_Core_Action::ADVANCED) { $values = $this->controller->exportValues('Advanced'); $fragment .= '/advanced'; } else { if ($this->_action == CRM_Core_Action::PROFILE) { $values = $this->controller->exportValues('Builder'); $fragment .= '/builder'; } else { if ($this->_action == CRM_Core_Action::COPY) { $values = $this->controller->exportValues('Custom'); $fragment .= '/custom'; } else { $values = $this->controller->exportValues('Basic'); } } } //set the user context for redirection of task actions $url = CRM_Utils_System::url('civicrm/contact/' . $fragment, 'force=1'); $session =& CRM_Core_Session::singleton(); $session->replaceUserContext($url); require_once 'CRM/Contact/Task.php'; $this->_task = $values['task']; $crmContactTaskTasks = CRM_Contact_Task::taskTitles(); $this->assign('taskName', $crmContactTaskTasks[$this->_task]); // all contacts or action = save a search if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_all' || $this->_task == CRM_Contact_Task::SAVE_SEARCH) { // need to perform action on all contacts // fire the query again and get the contact id's + display name $sortID = null; if ($this->get(CRM_Utils_Sort::SORT_ID)) { $sortID = CRM_Utils_Sort::sortIDValue($this->get(CRM_Utils_Sort::SORT_ID), $this->get(CRM_Utils_Sort::SORT_DIRECTION)); } $selectorName = $this->controller->selectorName(); require_once str_replace('_', DIRECTORY_SEPARATOR, $selectorName) . '.php'; $fv = $this->get('formValues'); $customClass = $this->get('customSearchClass'); require_once "CRM/Core/BAO/Mapping.php"; $returnProperties = CRM_Core_BAO_Mapping::returnProperties($values); eval('$selector =& new ' . $selectorName . '( $customClass, $fv, null, $returnProperties ); '); $params = $this->get('queryParams'); // fix for CRM-5165 $sortByCharacter = $this->get('sortByCharacter'); if ($sortByCharacter && $sortByCharacter != 1) { $params[] = array('sortByCharacter', '=', $sortByCharacter, 0, 0); } $dao =& $selector->contactIDQuery($params, $this->_action, $sortID); while ($dao->fetch()) { $this->_contactIds[] = $dao->contact_id; } } else { if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_sel') { // selected contacts only // need to perform action on only selected contacts foreach ($values as $name => $value) { if (substr($name, 0, CRM_Core_Form::CB_PREFIX_LEN) == CRM_Core_Form::CB_PREFIX) { $this->_contactIds[] = substr($name, CRM_Core_Form::CB_PREFIX_LEN); } } } } //contact type for pick up profiles as per selected contact types with subtypes //CRM-5521 if ($selectedTypes = CRM_Utils_Array::value('contact_type', $values)) { $selectedTypes = explode(" ", $selectedTypes); foreach ($selectedTypes as $ct => $dontcare) { if (strpos($ct, CRM_Core_DAO::VALUE_SEPARATOR) === false) { $this->_contactTypes[] = $ct; } else { $separator = strpos($ct, CRM_Core_DAO::VALUE_SEPARATOR); $this->_contactTypes[] = substr($ct, $separator + 1); } } } if (!empty($this->_contactIds)) { $this->_componentClause = ' contact_a.id IN ( ' . implode(',', $this->_contactIds) . ' ) '; $this->assign('totalSelectedContacts', count($this->_contactIds)); $this->_componentIds = $this->_contactIds; } }