+ /**
+ * @param $savedSearchID
+ * @param array $savedSearch
+ * @return array
+ * @throws API_Exception
+ * @throws \Civi\API\Exception\NotImplementedException
+ * @throws CRM_Core_Exception
+ */
+ protected static function getApiSQL($savedSearchID, array $savedSearch): array {
+ $api = \Civi\API\Request::create($savedSearch['api_entity'], 'get', $savedSearch['api_params']);
+ $query = new \Civi\Api4\Query\Api4SelectQuery($api->getEntityName(), FALSE, $api->entityFields());
+ $query->select = ['id'];
+ $query->where = $api->getWhere();
+ $query->orderBy = $api->getOrderBy();
+ $query->limit = $api->getLimit();
+ $query->offset = $api->getOffset();
+ $sql = $query->getSql();
+ return [
+ 'select' => substr($sql, 0, strpos($sql, 'FROM')),
+ 'from' => substr($sql, strpos($sql, 'FROM')),
+ ];
+ }
+
+ /**
+ * Get sql from a custom search.
+ *
+ * @param int $savedSearchID
+ * @param array $ssParams
+ *
+ * @return array
+ * @throws \Exception
+ */
+ protected static function getCustomSearchSQL($savedSearchID, array $ssParams): array {
+ // 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 (strpos($searchSQL, 'WHERE') === FALSE) {
+ $searchSQL .= " WHERE ( 1 ) ";
+ }
+ $sql = [
+ 'select' => substr($searchSQL, 0, strpos($searchSQL, 'FROM')),
+ 'from' => substr($searchSQL, strpos($searchSQL, 'FROM')),
+ ];
+ return $sql;
+ }
+
+ /**
+ * Get array of sql from a saved query object group.
+ *
+ * @param int $savedSearchID
+ * @param array $ssParams
+ *
+ * @return array
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
+ protected static function getQueryObjectSQL($savedSearchID, array $ssParams): array {
+ $returnProperties = NULL;
+ 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);
+ }
+ $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;
+ $sqlParts = $query->getSearchSQLParts(
+ 0, 0, NULL,
+ FALSE, FALSE,
+ FALSE, TRUE
+ );
+ $sql = [
+ 'select' => $sqlParts['select'],
+ 'from' => "{$sqlParts['from']} {$sqlParts['where']} {$sqlParts['having']} {$sqlParts['group_by']}",
+ ];
+ return $sql;
+ }
+