/** * 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(); }
/** * Processing needed for buildForm and later. */ public function preProcess() { // set the various class variables $this->_group = CRM_Core_PseudoConstant::group(); $this->_groupIterator = CRM_Core_PseudoConstant::groupIterator(); $this->_tag = CRM_Core_BAO_Tag::getTags(); $this->_done = FALSE; /* * we allow the controller to set force/reset externally, useful when we are being * driven by the wizard framework */ $this->_reset = CRM_Utils_Request::retrieve('reset', 'Boolean', CRM_Core_DAO::$_nullObject); $this->_force = CRM_Utils_Request::retrieve('force', 'Boolean', CRM_Core_DAO::$_nullObject); $this->_groupID = CRM_Utils_Request::retrieve('gid', 'Positive', $this); $this->_amtgID = CRM_Utils_Request::retrieve('amtgID', 'Positive', $this); $this->_ssID = CRM_Utils_Request::retrieve('ssID', 'Positive', $this); $this->_sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', $this); $this->_ufGroupID = CRM_Utils_Request::retrieve('id', 'Positive', $this); $this->_componentMode = CRM_Utils_Request::retrieve('component_mode', 'Positive', $this, FALSE, 1, $_REQUEST); $this->_operator = CRM_Utils_Request::retrieve('operator', 'String', $this, FALSE, 1, $_REQUEST, 'AND'); /** * set the button names */ $this->_searchButtonName = $this->getButtonName('refresh'); $this->_actionButtonName = $this->getButtonName('next', 'action'); $this->assign('actionButtonName', $this->_actionButtonName); // reset from session, CRM-3526 $session = CRM_Core_Session::singleton(); if ($this->_force && $session->get('selectedSearchContactIds')) { $session->resetScope('selectedSearchContactIds'); } // if we dont get this from the url, use default if one exsts $config = CRM_Core_Config::singleton(); if ($this->_ufGroupID == NULL && $config->defaultSearchProfileID != NULL) { $this->_ufGroupID = $config->defaultSearchProfileID; } // assign context to drive the template display, make sure context is valid $this->_context = CRM_Utils_Request::retrieve('context', 'String', $this, FALSE, 'search'); if (!CRM_Utils_Array::value($this->_context, self::validContext())) { $this->_context = 'search'; } $this->set('context', $this->_context); $this->assign('context', $this->_context); $this->_modeValue = self::getModeValue($this->_componentMode); $this->assign($this->_modeValue); $this->set('selectorName', self::$_selectorName); // get user submitted values // get it from controller only if form has been submitted, else preProcess has set this // $this->controller->isModal( ) returns TRUE if page is // valid, i.e all the validations are TRUE if (!empty($_POST) && !$this->controller->isModal()) { $this->_formValues = $this->controller->exportValues($this->_name); $this->normalizeFormValues(); $this->_params = CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); // also get the uf group id directly from the post value $this->_ufGroupID = CRM_Utils_Array::value('uf_group_id', $_POST, $this->_ufGroupID); $this->_formValues['uf_group_id'] = $this->_ufGroupID; $this->set('id', $this->_ufGroupID); // also get the object mode directly from the post value $this->_componentMode = CRM_Utils_Array::value('component_mode', $_POST, $this->_componentMode); // also get the operator from the post value if set $this->_operator = CRM_Utils_Array::value('operator', $_POST, $this->_operator); $this->_formValues['operator'] = $this->_operator; $this->set('operator', $this->_operator); } else { $this->_formValues = $this->get('formValues'); $this->_params = CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); if (!empty($this->_ufGroupID)) { $this->set('id', $this->_ufGroupID); } } if (empty($this->_formValues)) { //check if group is a smart group (fix for CRM-1255) if ($this->_groupID) { if ($ssId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $this->_groupID, 'saved_search_id')) { $this->_ssID = $ssId; } } // fix for CRM-1907 if (isset($this->_ssID) && $this->_context != 'smog') { // we only retrieve the saved search values if out current values are null $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID); //fix for CRM-1505 if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $this->_ssID, 'mapping_id')) { $this->_params = CRM_Contact_BAO_SavedSearch::getSearchParams($this->_ssID); } else { $this->_params = CRM_Contact_BAO_Query::convertFormValues($this->_formValues); } $this->_returnProperties =& $this->returnProperties(); } else { if (isset($this->_ufGroupID)) { // also set the uf group id if not already present $this->_formValues['uf_group_id'] = $this->_ufGroupID; } if (isset($this->_componentMode)) { $this->_formValues['component_mode'] = $this->_componentMode; } if (isset($this->_operator)) { $this->_formValues['operator'] = $this->_operator; } // FIXME: we should generalise in a way that components could inject url-filters // just like they build their own form elements foreach (array('mailing_id', 'mailing_delivery_status', 'mailing_open_status', 'mailing_click_status', 'mailing_reply_status', 'mailing_optout', 'mailing_forward', 'mailing_unsubscribe', 'mailing_date_low', 'mailing_date_high') as $mailingFilter) { $type = 'String'; if ($mailingFilter == 'mailing_id' && ($filterVal = CRM_Utils_Request::retrieve('mailing_id', 'Positive', $this))) { $this->_formValues[$mailingFilter] = array($filterVal); } elseif ($filterVal = CRM_Utils_Request::retrieve($mailingFilter, $type, $this)) { $this->_formValues[$mailingFilter] = $filterVal; } if ($filterVal) { $this->_openedPanes['Mailings'] = 1; $this->_formValues['hidden_CiviMail'] = 1; } } } } $this->assign('id', CRM_Utils_Array::value('uf_group_id', $this->_formValues)); $operator = CRM_Utils_Array::value('operator', $this->_formValues, 'AND'); $this->set('queryOperator', $operator); if ($operator == 'OR') { $this->assign('operator', ts('OR')); } else { $this->assign('operator', ts('AND')); } // show the context menu only when we’re not searching for deleted contacts; CRM-5673 if (empty($this->_formValues['deleted_contacts'])) { $menuItems = CRM_Contact_BAO_Contact::contextMenu(); $primaryActions = CRM_Utils_Array::value('primaryActions', $menuItems, array()); $this->_contextMenu = CRM_Utils_Array::value('moreActions', $menuItems, array()); $this->assign('contextMenu', $primaryActions + $this->_contextMenu); } if (!isset($this->_componentMode)) { $this->_componentMode = CRM_Contact_BAO_Query::MODE_CONTACTS; } $modeValues = self::getModeValue($this->_componentMode); self::$_selectorName = $this->_modeValue['selectorName']; $setDynamic = FALSE; if (strpos(self::$_selectorName, 'CRM_Contact_Selector') !== FALSE) { $selector = new self::$_selectorName($this->_customSearchClass, $this->_formValues, $this->_params, $this->_returnProperties, $this->_action, FALSE, TRUE, $this->_context, $this->_contextMenu); $setDynamic = TRUE; } else { $selector = new self::$_selectorName($this->_params, $this->_action, NULL, FALSE, NULL, "search", "advanced"); } $selector->setKey($this->controller->_key); $controller = new CRM_Contact_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $this->get(CRM_Utils_Sort::SORT_ID), CRM_Core_Action::VIEW, $this, CRM_Core_Selector_Controller::TRANSFER); $controller->setEmbedded(TRUE); $controller->setDynamicAction($setDynamic); if ($this->_force) { $this->postProcess(); /* * Note that we repeat this, since the search creates and stores * values that potentially change the controller behavior. i.e. things * like totalCount etc */ $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)); } $controller = new CRM_Contact_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $sortID, CRM_Core_Action::VIEW, $this, CRM_Core_Selector_Controller::TRANSFER); $controller->setEmbedded(TRUE); $controller->setDynamicAction($setDynamic); } $controller->moveFromSessionToTemplate(); }
/** * This method is called for processing a submitted search form. */ public function postProcess() { $this->set('isAdvanced', '0'); $this->set('isSearchBuilder', '0'); // get user submitted values // get it from controller only if form has been submitted, else preProcess has set this if (!empty($_POST)) { $this->_formValues = $this->controller->exportValues($this->_name); } if (isset($this->_groupID) && empty($this->_formValues['group'])) { $this->_formValues['group'] = $this->_groupID; } elseif (isset($this->_ssID) && empty($_POST)) { // if we are editing / running a saved search and the form has not been posted $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID); //fix for CRM-1505 if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $this->_ssID, 'mapping_id')) { $this->_params = CRM_Contact_BAO_SavedSearch::getSearchParams($this->_ssID); } } // we dont want to store the sortByCharacter in the formValue, it is more like // a filter on the result set // this filter is reset if we click on the search button if ($this->_sortByCharacter !== NULL && empty($_POST)) { if (strtolower($this->_sortByCharacter) == 'all') { $this->_formValues['sortByCharacter'] = NULL; } else { $this->_formValues['sortByCharacter'] = $this->_sortByCharacter; } } else { $this->_sortByCharacter = NULL; } $this->_params = CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); parent::postProcess(); }
/** * processing needed for buildForm and later * * @return void * @access public */ function preProcess() { /** * set the varios class variables */ $this->_group =& CRM_Core_PseudoConstant::group(); $this->_groupIterator =& CRM_Core_PseudoConstant::groupIterator(); $this->_tag =& CRM_Core_PseudoConstant::tag(); $this->_done = false; /** * set the button names */ $this->_searchButtonName = $this->getButtonName('refresh'); $this->_printButtonName = $this->getButtonName('next', 'print'); $this->_actionButtonName = $this->getButtonName('next', 'action'); /* * we allow the controller to set force/reset externally, useful when we are being * driven by the wizard framework */ $this->_reset = CRM_Utils_Request::retrieve('reset', 'Boolean', CRM_Core_DAO::$_nullObject); $this->_force = CRM_Utils_Request::retrieve('force', 'Boolean', CRM_Core_DAO::$_nullObject); $this->_groupID = CRM_Utils_Request::retrieve('gid', 'Positive', $this); $this->_amtgID = CRM_Utils_Request::retrieve('amtgID', 'Positive', $this); $this->_ssID = CRM_Utils_Request::retrieve('ssID', 'Positive', $this); $this->_sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', $this); $this->_ufGroupID = CRM_Utils_Request::retrieve('id', 'Positive', $this); // reset from session, CRM-3526 $session =& CRM_Core_Session::singleton(); if ($this->_force && $session->get('selectedSearchContactIds')) { $session->resetScope('selectedSearchContactIds'); } // if we dont get this from the url, use default if one exsts $config =& CRM_Core_Config::singleton(); if ($this->_ufGroupID == null && $config->defaultSearchProfileID != null) { $this->_ufGroupID = $config->defaultSearchProfileID; } /* * assign context to drive the template display, make sure context is valid */ $this->_context = CRM_Utils_Request::retrieve('context', 'String', $this, false, 'search'); if (!CRM_Utils_Array::value($this->_context, self::validContext())) { $this->_context = 'search'; $this->set('context', $this->_context); } $this->assign('context', $this->_context); $this->set('selectorName', $this->_selectorName); // get user submitted values // get it from controller only if form has been submitted, else preProcess has set this // $this->controller->isModal( ) returns true if page is // valid, i.e all the validations are true if (!empty($_POST) && !$this->controller->isModal()) { $this->_formValues = $this->controller->exportValues($this->_name); $this->normalizeFormValues(); $this->_params =& CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); // also get the uf group id directly from the post value $this->_ufGroupID = CRM_Utils_Array::value('uf_group_id', $_POST, $this->_ufGroupID); $this->_formValues['uf_group_id'] = $this->_ufGroupID; $this->set('id', $this->_ufGroupID); } else { $this->_formValues = $this->get('formValues'); $this->_params =& CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); } if (empty($this->_formValues)) { //check if group is a smart group (fix for CRM-1255) if ($this->_groupID) { if ($ssId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $this->_groupID, 'saved_search_id')) { $this->_ssID = $ssId; } } // fix for CRM-1907 if (isset($this->_ssID) && $this->_context != 'smog') { // we only retrieve the saved search values if out current values are null $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID); //fix for CRM-1505 if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $this->_ssID, 'mapping_id')) { $this->_params =& CRM_Contact_BAO_SavedSearch::getSearchParams($this->_ssID); } else { $this->_params =& CRM_Contact_BAO_Query::convertFormValues($this->_formValues); } $this->_returnProperties =& $this->returnProperties(); } else { if (isset($this->_ufGroupID)) { // also set the uf group id if not already present $this->_formValues['uf_group_id'] = $this->_ufGroupID; } } } $this->assign('id', CRM_Utils_Array::value('uf_group_id', $this->_formValues)); require_once 'CRM/Contact/BAO/Contact.php'; $menuItems = CRM_Contact_BAO_Contact::contextMenu(); $primaryActions = CRM_Utils_Array::value('primaryActions', $menuItems, array()); $this->_contextMenu = CRM_Utils_Array::value('moreActions', $menuItems, array()); $this->assign('contextMenu', $primaryActions + $this->_contextMenu); // CRM_Core_Error::debug( 'f', $this->_formValues ); // CRM_Core_Error::debug( 'p', $this->_params ); eval('$selector =& new ' . $this->_selectorName . '( $this->_customSearchClass, $this->_formValues, $this->_params, $this->_returnProperties, $this->_action, false, true, $this->_context );'); $controller =& new CRM_Contact_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $this->get(CRM_Utils_Sort::SORT_ID), CRM_Core_Action::VIEW, $this, CRM_Core_Selector_Controller::TRANSFER); $controller->setEmbedded(true); if ($this->_force) { $this->postProcess(); /* * Note that we repeat this, since the search creates and stores * values that potentially change the controller behavior. i.e. things * like totalCount etc */ $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)); } $controller =& new CRM_Contact_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $sortID, CRM_Core_Action::VIEW, $this, CRM_Core_Selector_Controller::TRANSFER); $controller->setEmbedded(true); } $controller->moveFromSessionToTemplate(); }
/** * this method is called for processing a submitted search form * * @return void * @access public */ function postProcess() { $session =& CRM_Core_Session::singleton(); $session->set('isAdvanced', '0'); $session->set('isSearchBuilder', '0'); // get user submitted values // get it from controller only if form has been submitted, else preProcess has set this if (!empty($_POST)) { $this->_formValues = $this->controller->exportValues($this->_name); $this->normalizeFormValues(); } if (isset($this->_groupID) && !CRM_Utils_Array::value('group', $this->_formValues)) { $this->_formValues['group'][$this->_groupID] = 1; } else { if (isset($this->_ssID) && empty($_POST)) { // if we are editing / running a saved search and the form has not been posted $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID); //fix for CRM-1505 if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_SavedSearch', $this->_ssID, 'mapping_id')) { $this->_params =& CRM_Contact_BAO_SavedSearch::getSearchParams($this->_ssID); } } } // we dont want to store the sortByCharacter in the formValue, it is more like // a filter on the result set // this filter is reset if we click on the search button if ($this->_sortByCharacter && empty($_POST)) { if ($this->_sortByCharacter == 1) { $this->_formValues['sortByCharacter'] = null; } else { $this->_formValues['sortByCharacter'] = $this->_sortByCharacter; } } $this->_params =& CRM_Contact_BAO_Query::convertFormValues($this->_formValues); $this->_returnProperties =& $this->returnProperties(); // CRM_Core_Error::debug( 'f', $this->_formValues ); // CRM_Core_Error::debug( 'p', $this->_params ); parent::postProcess(); }
/** * 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); } } }