コード例 #1
0
 /**
  * Generate a query to locate recipients who match the given
  * schedule.
  *
  * @param \CRM_Core_DAO_ActionSchedule $schedule
  *   The schedule as configured by the administrator.
  * @param string $phase
  *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
  * @return \CRM_Utils_SQL_Select
  * @see RecipientBuilder
  * @throws \CRM_Core_Exception
  */
 public function createQuery($schedule, $phase, $defaultParams)
 {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
     $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_activity e';
     $query['casContactIdField'] = 'r.contact_id';
     $query['casEntityIdField'] = 'e.id';
     $query['casContactTableAlias'] = NULL;
     $query['casDateField'] = 'e.activity_date_time';
     if (!is_null($schedule->limit_to)) {
         $activityContacts = \CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
         if ($schedule->limit_to == 0 || !isset($activityContacts[$schedule->recipient])) {
             $recipientTypeId = \CRM_Utils_Array::key('Activity Targets', $activityContacts);
         } else {
             $recipientTypeId = $schedule->recipient;
         }
         $query->join('r', "INNER JOIN civicrm_activity_contact r ON r.activity_id = e.id AND record_type_id = {$recipientTypeId}");
     }
     // build where clause
     if (!empty($selectedValues)) {
         $query->where("e.activity_type_id IN (#selectedValues)")->param('selectedValues', $selectedValues);
     } else {
         $query->where("e.activity_type_id IS NULL");
     }
     if (!empty($selectedStatuses)) {
         $query->where("e.status_id IN (#selectedStatuss)")->param('selectedStatuss', $selectedStatuses);
     }
     $query->where('e.is_current_revision = 1 AND e.is_deleted = 0');
     return $query;
 }
コード例 #2
0
 /**
  * Joins onto a custom field
  *
  * Adds a join to the query to make this field available for use in a clause.
  *
  * @param array $customField
  * @param string $baseTable
  * @return array
  *   Returns the table and field name for adding this field to a SELECT or WHERE clause
  */
 private function addCustomField($customField, $baseTable = 'a')
 {
     $tableName = $customField["table_name"];
     $columnName = $customField["column_name"];
     $tableAlias = "{$baseTable}_to_{$tableName}";
     $this->query->join($tableAlias, "LEFT JOIN `{$tableName}` `{$tableAlias}` ON `{$tableAlias}`.entity_id = `{$baseTable}`.id");
     return array($tableAlias, $columnName);
 }
コード例 #3
0
 /**
  * @param string $side
  * @param string $tableName
  * @param string $tableAlias
  * @param array $conditions
  */
 public function join($side, $tableName, $tableAlias, $conditions)
 {
     // INNER JOINs take precedence over LEFT JOINs
     if ($side != 'LEFT' || !isset($this->joins[$tableAlias])) {
         $this->joins[$tableAlias] = $side;
         $this->query->join($tableAlias, "{$side} JOIN `{$tableName}` `{$tableAlias}` ON " . implode(' AND ', $conditions));
     }
 }
コード例 #4
0
ファイル: SelectQuery.php プロジェクト: nielosz/civicrm-core
 /**
  * Populate $this->selectFields
  *
  * @throws \Civi\API\Exception\UnauthorizedException
  */
 protected function buildSelectFields()
 {
     $return_all_fields = empty($this->select) || !is_array($this->select);
     $return = $return_all_fields ? $this->entityFieldNames : $this->select;
     if ($return_all_fields || in_array('custom', $this->select)) {
         foreach (array_keys($this->apiFieldSpec) as $fieldName) {
             if (strpos($fieldName, 'custom_') === 0) {
                 $return[] = $fieldName;
             }
         }
     }
     // Always select the ID.
     $this->selectFields[self::MAIN_TABLE_ALIAS . ".id"] = "id";
     // core return fields
     foreach ($return as $fieldName) {
         $field = $this->getField($fieldName);
         if ($field && in_array($field['name'], $this->entityFieldNames)) {
             $this->selectFields[self::MAIN_TABLE_ALIAS . ".{$field['name']}"] = $field['name'];
         } elseif (strpos($fieldName, '.')) {
             $fkField = $this->addFkField($fieldName, 'LEFT');
             if ($fkField) {
                 $this->selectFields[implode('.', $fkField)] = $fieldName;
             }
         } elseif ($field && strpos($fieldName, 'custom_') === 0) {
             list($table_name, $column_name) = $this->addCustomField($field, 'LEFT');
             if ($field['data_type'] != 'ContactReference') {
                 // 'ordinary' custom field. We will select the value as custom_XX.
                 $this->selectFields["{$table_name}.{$column_name}"] = $fieldName;
             } else {
                 // contact reference custom field. The ID will be stored in custom_XX_id.
                 // custom_XX will contain the sort name of the contact.
                 $this->query->join("c_{$fieldName}", "LEFT JOIN civicrm_contact c_{$fieldName} ON c_{$fieldName}.id = `{$table_name}`.`{$column_name}`");
                 $this->selectFields["{$table_name}.{$column_name}"] = $fieldName . "_id";
                 // We will call the contact table for the join c_XX.
                 $this->selectFields["c_{$fieldName}.sort_name"] = $fieldName;
             }
         }
     }
 }
コード例 #5
0
 /**
  * Orders the query by one or more fields
  *
  * e.g.
  * @code
  *   $this->orderBy(array('last_name DESC', 'birth_date'));
  * @endcode
  *
  * @param string|array $sortParams
  * @throws \API_Exception
  * @throws \Civi\API\Exception\UnauthorizedException
  */
 public function orderBy($sortParams)
 {
     $orderBy = array();
     foreach (is_array($sortParams) ? $sortParams : explode(',', $sortParams) as $item) {
         $words = preg_split("/[\\s]+/", trim($item));
         if ($words) {
             // Direction defaults to ASC unless DESC is specified
             $direction = strtoupper(\CRM_Utils_Array::value(1, $words, '')) == 'DESC' ? ' DESC' : '';
             $field = $this->getField($words[0]);
             if ($field) {
                 $orderBy[] = self::MAIN_TABLE_ALIAS . '.' . $field['name'] . $direction;
             } elseif (strpos($words[0], '.')) {
                 $join = $this->addFkField($words[0]);
                 if ($join) {
                     $orderBy[] = "`{$join[0]}`.`{$join[1]}`{$direction}";
                 }
             } else {
                 throw new \API_Exception("Unknown field specified for sort. Cannot order by '{$item}'");
             }
         }
     }
     $this->query->orderBy($orderBy);
 }
コード例 #6
0
ファイル: ByPage.php プロジェクト: FundingWorks/civicrm-core
 /**
  * Generate a query to locate contacts who match the given
  * schedule.
  *
  * @param \CRM_Core_DAO_ActionSchedule $schedule
  * @param string $phase
  *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
  * @param array $defaultParams
  *   Default parameters that should be included with query.
  * @return \CRM_Utils_SQL_Select
  * @see RecipientBuilder
  * @throws CRM_Core_Exception
  */
 public function createQuery($schedule, $phase, $defaultParams)
 {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
     $query = \CRM_Utils_SQL_Select::from("civicrm_contribution e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_contribution e';
     $query['casContactIdField'] = 'e.contact_id';
     $query['casEntityIdField'] = 'e.id';
     $query['casContactTableAlias'] = NULL;
     // $schedule->start_action_date is user-supplied data. validate.
     if (!array_key_exists($schedule->start_action_date, $this->getDateFields())) {
         throw new CRM_Core_Exception("Invalid date field");
     }
     $query['casDateField'] = $schedule->start_action_date;
     // build where clause
     if (!empty($selectedValues)) {
         $query->where("e.contribution_page_id IN (@selectedValues)")->param('selectedValues', $selectedValues);
     }
     if (!empty($selectedStatuses)) {
         $query->where("e.contribution_status_id IN (#selectedStatuses)")->param('selectedStatuses', $selectedStatuses);
     }
     return $query;
 }
コード例 #7
0
 /**
  * Generate a query to locate recipients who match the given
  * schedule.
  *
  * @param \CRM_Core_DAO_ActionSchedule $schedule
  *   The schedule as configured by the administrator.
  * @param string $phase
  *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
  * @param array $defaultParams
  *
  * @return \CRM_Utils_SQL_Select
  * @see RecipientBuilder
  */
 public function createQuery($schedule, $phase, $defaultParams)
 {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
     $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_event r';
     $query['casContactIdField'] = 'e.contact_id';
     $query['casEntityIdField'] = 'e.id';
     $query['casContactTableAlias'] = NULL;
     $query['casDateField'] = str_replace('event_', 'r.', $schedule->start_action_date);
     $query->join('r', 'INNER JOIN civicrm_event r ON e.event_id = r.id');
     if ($schedule->recipient_listing && $schedule->limit_to) {
         switch ($schedule->recipient) {
             case 'participant_role':
                 $query->where("e.role_id IN (#recipList)")->param('recipList', \CRM_Utils_Array::explodePadded($schedule->recipient_listing));
                 break;
             default:
                 break;
         }
     }
     // build where clause
     if (!empty($selectedValues)) {
         $valueField = $this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID ? 'event_type_id' : 'id';
         $query->where("r.{$valueField} IN (@selectedValues)")->param('selectedValues', $selectedValues);
     } else {
         $query->where($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID ? "r.event_type_id IS NULL" : "r.id IS NULL");
     }
     $query->where('r.is_active = 1');
     $query->where('r.is_template = 0');
     // participant status criteria not to be implemented for additional recipients
     // ... why not?
     if (!empty($selectedStatuses)) {
         switch ($phase) {
             case RecipientBuilder::PHASE_RELATION_FIRST:
             case RecipientBuilder::PHASE_RELATION_REPEAT:
                 $query->where("e.status_id IN (#selectedStatuses)")->param('selectedStatuses', $selectedStatuses);
                 break;
         }
     }
     return $query;
 }
コード例 #8
0
 /**
  * Add a JOIN clause like "INNER JOIN civicrm_action_log reminder ON...".
  *
  * @param string $joinType
  *   Join type (eg INNER JOIN, LEFT JOIN).
  * @param string $for
  *    Ex: 'rel', 'addl'.
  * @param \CRM_Utils_SQL_Select $query
  * @return \CRM_Utils_SQL_Select
  * @throws \CRM_Core_Exception
  */
 protected function joinReminder($joinType, $for, $query)
 {
     switch ($for) {
         case 'rel':
             $contactIdField = $query['casContactIdField'];
             $entityName = $this->mapping->getEntity();
             $entityIdField = $query['casEntityIdField'];
             break;
         case 'addl':
             $contactIdField = 'c.id';
             $entityName = 'civicrm_contact';
             $entityIdField = 'c.id';
             break;
         default:
             throw new \CRM_Core_Exception("Unrecognized 'for': {$for}");
     }
     $joinClause = "civicrm_action_log reminder ON reminder.contact_id = {$contactIdField} AND\nreminder.entity_id          = {$entityIdField} AND\nreminder.entity_table       = '{$entityName}' AND\nreminder.action_schedule_id = {$this->actionSchedule->id}";
     // Why do we only include anniversary clause for 'rel' queries?
     if ($for === 'rel' && !empty($query['casAnniversaryMode'])) {
         // only consider reminders less than 11 months ago
         $joinClause .= " AND reminder.action_date_time > DATE_SUB(!casNow, INTERVAL 11 MONTH)";
     }
     return \CRM_Utils_SQL_Select::fragment()->join("reminder", "{$joinType} {$joinClause}");
 }
コード例 #9
0
 function testInterpolateBadKey()
 {
     try {
         $result = CRM_Utils_SQL_Select::from('ignore')->interpolate('this is a {var}', array('{var}' => 'not a well-formed variable name'));
         $this->fail('Expected exception; got: ' . var_export($result, TRUE));
     } catch (CRM_Core_Exception $e) {
         $this->assertTrue(TRUE, "Caught expected exception");
     }
 }
コード例 #10
0
 /**
  * Generate a query to locate recipients who match the given
  * schedule.
  *
  * @param \CRM_Core_DAO_ActionSchedule $schedule
  *   The schedule as configured by the administrator.
  * @param string $phase
  *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
  * @param array $defaultParams
  *
  * @return \CRM_Utils_SQL_Select
  * @throws \CRM_Core_Exception
  * @see RecipientBuilder
  */
 public function createQuery($schedule, $phase, $defaultParams)
 {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
     // FIXME: This assumes that $values only has one field, but UI shows multiselect.
     // Properly supporting multiselect would require total rewrite of this function.
     if (count($selectedValues) != 1 || !isset($selectedValues[0])) {
         throw new \CRM_Core_Exception("Error: Scheduled reminders may only have one contact field.");
     } elseif (in_array($selectedValues[0], $this->contactDateFields)) {
         $dateDBField = $selectedValues[0];
         $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
         $query->param(array('casAddlCheckFrom' => 'civicrm_contact e', 'casContactIdField' => 'e.id', 'casEntityIdField' => 'e.id', 'casContactTableAlias' => 'e'));
         $query->where('e.is_deleted = 0 AND e.is_deceased = 0');
     } else {
         //custom field
         $customFieldParams = array('id' => substr($selectedValues[0], 7));
         $customGroup = $customField = array();
         \CRM_Core_BAO_CustomField::retrieve($customFieldParams, $customField);
         $dateDBField = $customField['column_name'];
         $customGroupParams = array('id' => $customField['custom_group_id'], $customGroup);
         \CRM_Core_BAO_CustomGroup::retrieve($customGroupParams, $customGroup);
         $query = \CRM_Utils_SQL_Select::from("{$customGroup['table_name']} e")->param($defaultParams);
         $query->param(array('casAddlCheckFrom' => "{$customGroup['table_name']} e", 'casContactIdField' => 'e.entity_id', 'casEntityIdField' => 'e.id', 'casContactTableAlias' => NULL));
         $query->where('1');
         // possible to have no "where" in this case
     }
     $query['casDateField'] = 'e.' . $dateDBField;
     if (in_array(2, $selectedStatuses)) {
         $query['casAnniversaryMode'] = 1;
         $query['casDateField'] = 'DATE_ADD(' . $query['casDateField'] . ', INTERVAL ROUND(DATEDIFF(DATE(' . $query['casNow'] . '), ' . $query['casDateField'] . ') / 365) YEAR)';
     }
     return $query;
 }
コード例 #11
0
ファイル: ByType.php プロジェクト: nielosz/civicrm-core
 /**
  * Generate a query to locate contacts who match the given
  * schedule.
  *
  * @param \CRM_Core_DAO_ActionSchedule $schedule
  * @param string $phase
  *   See, e.g., RecipientBuilder::PHASE_RELATION_FIRST.
  * @param array $defaultParams
  *   Default parameters that should be included with query.
  * @return \CRM_Utils_SQL_Select
  * @see RecipientBuilder
  * @throws CRM_Core_Exception
  */
 public function createQuery($schedule, $phase, $defaultParams)
 {
     $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
     $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
     $query = \CRM_Utils_SQL_Select::from("civicrm_contribution e")->param($defaultParams);
     $query['casAddlCheckFrom'] = 'civicrm_contribution e';
     $query['casContactIdField'] = 'e.contact_id';
     $query['casEntityIdField'] = 'e.id';
     $query['casContactTableAlias'] = NULL;
     // $schedule->start_action_date is user-supplied data. validate.
     if (!array_key_exists($schedule->start_action_date, $this->getDateFields())) {
         throw new CRM_Core_Exception("Invalid date field");
     }
     $query['casDateField'] = $schedule->start_action_date;
     // build where clause
     if (!empty($selectedValues)) {
         $query->where("e.financial_type_id IN (@selectedValues)")->param('selectedValues', $selectedValues);
     }
     if (!empty($selectedStatuses)) {
         $query->where("e.contribution_status_id IN (#selectedStatuses)")->param('selectedStatuses', $selectedStatuses);
     }
     if ($schedule->recipient_listing && $schedule->limit_to) {
         switch ($schedule->recipient) {
             case 'soft_credit_type':
                 $query['casContactIdField'] = 'soft.contact_id';
                 $query->join('soft', 'INNER JOIN civicrm_contribution_soft soft ON soft.contribution_id = e.id')->where("soft.soft_credit_type_id IN (#recipList)")->param('recipList', \CRM_Utils_Array::explodePadded($schedule->recipient_listing));
                 break;
         }
     }
     return $query;
 }
コード例 #12
0
ファイル: Event.php プロジェクト: kcristiano/civicrm-core
/**
 * Get Event record.
 *
 * @param array $params
 *
 * @return array
 *   Array of all found event property values.
 */
function civicrm_api3_event_get($params)
{
    //legacy support for $params['return.sort']
    if (!empty($params['return.sort'])) {
        $params['options']['sort'] = $params['return.sort'];
        unset($params['return.sort']);
    }
    //legacy support for $params['return.offset']
    if (!empty($params['return.offset'])) {
        $params['options']['offset'] = $params['return.offset'];
        unset($params['return.offset']);
    }
    //legacy support for $params['return.max_results']
    if (!empty($params['return.max_results'])) {
        $params['options']['limit'] = $params['return.max_results'];
        unset($params['return.max_results']);
    }
    $sql = CRM_Utils_SQL_Select::fragment();
    if (!empty($params['isCurrent'])) {
        $sql->where('(start_date >= CURDATE() || end_date >= CURDATE())');
    }
    $events = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'Event', $sql, TRUE);
    $options = _civicrm_api3_get_options_from_params($params);
    if ($options['is_count']) {
        return civicrm_api3_create_success($events, $params, 'Event', 'get');
    }
    foreach ($events as $id => $event) {
        if (!empty($params['return.is_full'])) {
            _civicrm_api3_event_getisfull($events, $id);
        }
        _civicrm_api3_event_get_legacy_support_42($events, $id);
        if (!empty($options['return'])) {
            $events[$id]['price_set_id'] = CRM_Price_BAO_PriceSet::getFor('civicrm_event', $id);
        }
    }
    return civicrm_api3_create_success($events, $params, 'Event', 'get');
}
コード例 #13
0
 /**
  * Get a list of Projects matching the params.
  *
  * This function is invoked from within the web form layer and also from the
  * API layer. Special params include:
  * <ol>
  *   <li>project_contacts (@see CRM_Volunteer_BAO_Project::create() and
  *     CRM_Volunteer_BAO_Project::buildContactWhere)</li>
  *   <li>proximity (@see CRM_Volunteer_BAO_Project::buildProximityWhere)</li>
  * </ol>
  *
  * NOTE: This method does not return data related to the special params
  * outlined above; however, these parameters can be used to filter the list
  * of Projects that is returned.
  *
  * @param array $params
  * @return array of CRM_Volunteer_BAO_Project objects
  */
 public static function retrieve(array $params)
 {
     $result = array();
     $query = CRM_Utils_SQL_Select::from('`civicrm_volunteer_project` vp')->select('DISTINCT vp.*');
     if (!empty($params['project_contacts'])) {
         $contactJoin = self::buildContactJoin($params['project_contacts']);
         if ($contactJoin) {
             $query->join('vpc', $contactJoin);
         }
     }
     if (!empty($params['proximity'])) {
         $query->join('loc', 'INNER JOIN `civicrm_loc_block` loc ON loc.id = vp.loc_block_id')->join('civicrm_address', 'INNER JOIN `civicrm_address` ON civicrm_address.id = loc.address_id')->where(self::buildProximityWhere($params['proximity']));
     }
     // This step is here to support both naming conventions for specifying params
     // (e.g., volunteer_project_id and id) while normalizing how we access them
     // (e.g., $project->id)
     $project = new CRM_Volunteer_BAO_Project();
     $project->copyValues($params);
     foreach ($project->fields() as $field) {
         $fieldName = $field['name'];
         if (!empty($project->{$fieldName})) {
             $query->where('!column = @value', array('column' => $fieldName, 'value' => $project->{$fieldName}));
         }
     }
     $dao = self::executeQuery($query->toSQL());
     while ($dao->fetch()) {
         $fetchedProject = new CRM_Volunteer_BAO_Project();
         $fetchedProject->copyValues(clone $dao);
         $result[(int) $dao->id] = $fetchedProject;
     }
     $dao->free();
     return $result;
 }
コード例 #14
0
ファイル: Case.php プロジェクト: kcristiano/civicrm-core
/**
 * Get details of a particular case, or search for cases, depending on params.
 *
 * Please provide one (and only one) of the four get/search parameters:
 *
 * @param array $params
 *   'id' => if set, will get all available info about a case, including contacts and activities
 *
 *   // if no case_id provided, this function will use one of the following search parameters:
 *   'client_id' => finds all cases with a specific client
 *   'activity_id' => returns the case containing a specific activity
 *   'contact_id' => finds all cases associated with a contact (in any role, not just client)
 *
 * @throws API_Exception
 * @return array
 *   (get mode, case_id provided): Array with case details, case roles, case activity ids, (search mode, case_id not provided): Array of cases found
 */
function civicrm_api3_case_get($params)
{
    $options = _civicrm_api3_get_options_from_params($params);
    $sql = CRM_Utils_SQL_Select::fragment();
    // Add clause to search by client
    if (!empty($params['contact_id'])) {
        $contacts = array();
        foreach ((array) $params['contact_id'] as $c) {
            if (!CRM_Utils_Rule::positiveInteger($c)) {
                throw new API_Exception('Invalid parameter: contact_id. Must provide numeric value(s).');
            }
            $contacts[] = $c;
        }
        $sql->join('civicrm_case_contact', 'INNER JOIN civicrm_case_contact ON civicrm_case_contact.case_id = a.id')->where('civicrm_case_contact.contact_id IN (' . implode(',', $contacts) . ')');
    }
    // Add clause to search by activity
    if (!empty($params['activity_id'])) {
        if (!CRM_Utils_Rule::positiveInteger($params['activity_id'])) {
            throw new API_Exception('Invalid parameter: activity_id. Must provide a numeric value.');
        }
        $activityId = $params['activity_id'];
        $originalId = CRM_Core_DAO::getFieldValue('CRM_Activity_BAO_Activity', $activityId, 'original_id');
        if ($originalId) {
            $activityId .= ',' . $originalId;
        }
        $sql->join('civicrm_case_activity', 'INNER JOIN civicrm_case_activity ON civicrm_case_activity.case_id = a.id')->where("civicrm_case_activity.activity_id IN ({$activityId})");
    }
    $foundcases = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, TRUE, 'Case', $sql);
    if (empty($options['is_count'])) {
        // For historic reasons we return these by default only when fetching a case by id
        if (!empty($params['id']) && empty($options['return'])) {
            $options['return'] = array('contacts' => 1, 'activities' => 1, 'contact_id' => 1);
        }
        foreach ($foundcases['values'] as &$case) {
            _civicrm_api3_case_read($case, $options);
        }
    }
    return $foundcases;
}
コード例 #15
0
/**
 * Attachment find helper.
 *
 * @param array $params
 * @param int|null $id the user-supplied ID of the attachment record
 * @param array $file
 *   The user-supplied vales for the file (mime_type, description, upload_date).
 * @param array $entityFile
 *   The user-supplied values of the entity-file (entity_table, entity_id).
 * @param bool $isTrusted
 *
 * @return CRM_Core_DAO
 * @throws API_Exception
 */
function __civicrm_api3_attachment_find($params, $id, $file, $entityFile, $isTrusted)
{
    foreach (array('name', 'content', 'path', 'url') as $unsupportedFilter) {
        if (!empty($params[$unsupportedFilter])) {
            throw new API_Exception("Get by {$unsupportedFilter} is not currently supported");
        }
    }
    $select = CRM_Utils_SQL_Select::from('civicrm_file cf')->join('cef', 'INNER JOIN civicrm_entity_file cef ON cf.id = cef.file_id')->select(array('cf.id', 'cf.uri', 'cf.mime_type', 'cf.description', 'cf.upload_date', 'cef.entity_table', 'cef.entity_id'));
    if ($id) {
        $select->where('cf.id = #id', array('#id' => $id));
    }
    // Recall: $file is filtered by parse_params.
    foreach ($file as $key => $value) {
        $select->where('cf.!field = @value', array('!field' => $key, '@value' => $value));
    }
    // Recall: $entityFile is filtered by parse_params.
    foreach ($entityFile as $key => $value) {
        $select->where('cef.!field = @value', array('!field' => $key, '@value' => $value));
    }
    if (!$isTrusted) {
        // FIXME ACLs: Add any JOIN or WHERE clauses needed to enforce access-controls for the target entity.
        //
        // The target entity is identified by "cef.entity_table" (aka $entityFile['entity_table']) and "cef.entity_id".
        //
        // As a simplification, we *require* the "get" actions to filter on a single "entity_table" which should
        // avoid the complexity of matching ACL's against multiple entity types.
    }
    $dao = CRM_Core_DAO::executeQuery($select->toSQL());
    return $dao;
}
コード例 #16
0
ファイル: Activity.php プロジェクト: hyebahi/civicrm-core
/**
 * Gets a CiviCRM activity according to parameters.
 *
 * @param array $params
 *   Array per getfields documentation.
 *
 * @return array
 *   API result array
 */
function civicrm_api3_activity_get($params)
{
    if (!empty($params['contact_id'])) {
        $activities = CRM_Activity_BAO_Activity::getContactActivity($params['contact_id']);
        // BAO function doesn't actually return a contact ID - hack api for now & add to test so when api re-write
        // happens it won't get missed.
        foreach ($activities as $key => $activityArray) {
            $activities[$key]['id'] = $key;
        }
    } else {
        $sql = CRM_Utils_SQL_Select::fragment();
        $options = civicrm_api3('ActivityContact', 'getoptions', array('field' => 'record_type_id'));
        $options = $options['values'];
        $activityContactOptions = array('target_contact_id' => array_search('Activity Targets', $options), 'source_contact_id' => array_search('Activity Source', $options), 'assignee_contact_id' => array_search('Activity Assignees', $options));
        foreach ($activityContactOptions as $activityContactName => $activityContactValue) {
            if (!empty($params[$activityContactName])) {
                // If the intent is to have multiple joins -- one for each relation -- then you would
                // need different table aliases. Consider replacing 'ac' and passing in a '!alias' param,
                // with a different value for each relation.
                $sql->join('activity_' . $activityContactName, 'LEFT JOIN civicrm_activity_contact ac ON a.id = ac.activity_id AND ac.record_type_id = #typeId', array('typeId' => $activityContactValue));
                $sql->where('ac.contact_id IN (#cid)', array('cid' => $params[$activityContactName]));
            }
        }
        $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'Activity', $sql);
    }
    $options = _civicrm_api3_get_options_from_params($params, FALSE, 'Activity', 'get');
    if ($options['is_count']) {
        return civicrm_api3_create_success($activities, $params, 'Activity', 'get');
    }
    $activities = _civicrm_api3_activity_get_formatResult($params, $activities);
    //legacy custom data get - so previous formatted response is still returned too
    return civicrm_api3_create_success($activities, $params, 'Activity', 'get');
}
コード例 #17
0
 public function testArrayGet()
 {
     $select = CRM_Utils_SQL_Select::from("foo")->param('hello', 'world');
     $this->assertEquals('world', $select['hello']);
 }
コード例 #18
0
/**
 * Check for a UUID by entity type and ID.
 */
function _civicrm_api3_entity_id_find_by_uuid($entity_type, $uuid)
{
    $query = CRM_Utils_SQL_Select::from('civicrm_managed m')->select(array('m.id', 'm.uuid', 'm.entity_type', 'm.entity_id'))->where('m.uuid = @uuid', array('@uuid' => $uuid))->where('m.entity_type = @entity_type', array('@entity_type' => $entity_type))->where('m.module = @module', array('@module' => 'civicrm_configexport'))->toSQL();
    $dao = CRM_Core_DAO::executeQuery($query);
    if ($dao->fetch()) {
        return $dao->entity_id;
    }
}
コード例 #19
0
ファイル: Activity.php プロジェクト: kcristiano/civicrm-core
/**
 * Gets a CiviCRM activity according to parameters.
 *
 * @param array $params
 *   Array per getfields documentation.
 *
 * @return array API result array
 *   API result array
 *
 * @throws \API_Exception
 * @throws \CiviCRM_API3_Exception
 * @throws \Civi\API\Exception\UnauthorizedException
 */
function civicrm_api3_activity_get($params)
{
    if (!empty($params['check_permissions']) && !CRM_Core_Permission::check('view all activities')) {
        // In absence of view all activities permission it's possible to see a specific activity by ACL.
        // Note still allowing view all activities to override ACLs is based on the 'don't change too much
        // if you are not sure principle' and it could be argued that the ACLs should always be applied.
        if (empty($params['id']) || !empty($params['contact_id'])) {
            // We fall back to the original blunt permissions if we don't have an id to check or we are about
            // to go to the weird place that the legacy 'contact_id' parameter takes us to.
            throw new \Civi\API\Exception\UnauthorizedException("Cannot access activities. Required permission: 'view all activities''");
        }
        if (!CRM_Activity_BAO_Activity::checkPermission($params['id'], CRM_Core_Action::VIEW)) {
            throw new \Civi\API\Exception\UnauthorizedException('You do not have permission to view this activity');
        }
    }
    if (!empty($params['contact_id'])) {
        $activities = CRM_Activity_BAO_Activity::getContactActivity($params['contact_id']);
        // BAO function doesn't actually return a contact ID - hack api for now & add to test so when api re-write
        // happens it won't get missed.
        foreach ($activities as $key => $activityArray) {
            $activities[$key]['id'] = $key;
        }
    } else {
        $sql = CRM_Utils_SQL_Select::fragment();
        $options = civicrm_api3('ActivityContact', 'getoptions', array('field' => 'record_type_id'));
        $options = $options['values'];
        $activityContactOptions = array('target_contact_id' => array_search('Activity Targets', $options), 'source_contact_id' => array_search('Activity Source', $options), 'assignee_contact_id' => array_search('Activity Assignees', $options));
        foreach ($activityContactOptions as $activityContactName => $activityContactValue) {
            if (!empty($params[$activityContactName])) {
                // If the intent is to have multiple joins -- one for each relation -- then you would
                // need different table aliases. Consider replacing 'ac' and passing in a '!alias' param,
                // with a different value for each relation.
                $sql->join('activity_' . $activityContactName, 'LEFT JOIN civicrm_activity_contact ac ON a.id = ac.activity_id AND ac.record_type_id = #typeId', array('typeId' => $activityContactValue));
                $sql->where('ac.contact_id IN (#cid)', array('cid' => $params[$activityContactName]));
            }
        }
        $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'Activity', $sql);
    }
    $options = _civicrm_api3_get_options_from_params($params, FALSE, 'Activity', 'get');
    if ($options['is_count']) {
        return civicrm_api3_create_success($activities, $params, 'Activity', 'get');
    }
    $activities = _civicrm_api3_activity_get_formatResult($params, $activities);
    //legacy custom data get - so previous formatted response is still returned too
    return civicrm_api3_create_success($activities, $params, 'Activity', 'get');
}
コード例 #20
0
ファイル: Mailing.php プロジェクト: rameshrr99/civicrm-core
/**
 * Send test mailing.
 *
 * @param array $params
 *
 * @return array
 * @throws \API_Exception
 * @throws \CiviCRM_API3_Exception
 */
function civicrm_api3_mailing_send_test($params)
{
    if (!array_key_exists('test_group', $params) && !array_key_exists('test_email', $params)) {
        throw new API_Exception("Mandatory key(s) missing from params array: test_group and/or test_email field are required");
    }
    civicrm_api3_verify_mandatory($params, 'CRM_Mailing_DAO_MailingJob', array('mailing_id'), FALSE);
    $testEmailParams = _civicrm_api3_generic_replace_base_params($params);
    $testEmailParams['is_test'] = 1;
    $job = civicrm_api3('MailingJob', 'create', $testEmailParams);
    $testEmailParams['job_id'] = $job['id'];
    $testEmailParams['emails'] = explode(',', $testEmailParams['test_email']);
    if (!empty($params['test_email'])) {
        $query = CRM_Utils_SQL_Select::from('civicrm_email e')->select(array('e.id', 'e.contact_id', 'e.email'))->join('c', 'INNER JOIN civicrm_contact c ON e.contact_id = c.id')->where('e.email IN (@emails)', array('@emails' => $testEmailParams['emails']))->where('e.on_hold = 0')->where('c.is_opt_out = 0')->where('c.do_not_email = 0')->where('c.is_deceased = 0')->where('c.is_deleted = 0')->groupBy('e.id')->orderBy(array('e.is_bulkmail DESC', 'e.is_primary DESC'))->toSQL();
        $dao = CRM_Core_DAO::executeQuery($query);
        $emailDetail = array();
        // fetch contact_id and email id for all existing emails
        while ($dao->fetch()) {
            $emailDetail[$dao->email] = array('contact_id' => $dao->contact_id, 'email_id' => $dao->id);
        }
        $dao->free();
        foreach ($testEmailParams['emails'] as $key => $email) {
            $email = trim($email);
            $contactId = $emailId = NULL;
            if (array_key_exists($email, $emailDetail)) {
                $emailId = $emailDetail[$email]['email_id'];
                $contactId = $emailDetail[$email]['contact_id'];
            }
            if (!$contactId) {
                //create new contact.
                $contact = civicrm_api3('Contact', 'create', array('contact_type' => 'Individual', 'email' => $email, 'api.Email.get' => array('return' => 'id')));
                $contactId = $contact['id'];
                $emailId = $contact['values'][$contactId]['api.Email.get']['id'];
            }
            civicrm_api3('MailingEventQueue', 'create', array('job_id' => $job['id'], 'email_id' => $emailId, 'contact_id' => $contactId));
        }
    }
    $isComplete = FALSE;
    $config = CRM_Core_Config::singleton();
    $mailerJobSize = Civi::settings()->get('mailerJobSize');
    while (!$isComplete) {
        // Q: In CRM_Mailing_BAO_Mailing::processQueue(), the three runJobs*()
        // functions are all called. Why does Mailing.send_test only call one?
        // CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize, NULL);
        $isComplete = CRM_Mailing_BAO_MailingJob::runJobs($testEmailParams);
        // CRM_Mailing_BAO_MailingJob::runJobs_post(NULL);
    }
    //return delivered mail info
    $mailDelivered = CRM_Mailing_Event_BAO_Delivered::getRows($params['mailing_id'], $job['id'], TRUE, NULL, NULL, NULL, TRUE);
    return civicrm_api3_create_success($mailDelivered);
}
コード例 #21
0
ファイル: SelectTest.php プロジェクト: konadave/civicrm-core
 public function testInsertInto_WithDupes()
 {
     $select = CRM_Utils_SQL_Select::from('foo')->insertInto('bar', array('first', 'second', 'third', 'fourth'))->select('fid')->select('1')->select('fid')->select('1')->where('!field = #value', array('field' => 'zoo', 'value' => 3))->where('!field = #value', array('field' => 'aviary', 'value' => 3))->where('!field = #value', array('field' => 'zoo', 'value' => 3))->groupBy('!colName', array('colName' => 'noodle'))->groupBy('!colName', array('colName' => 'sauce'))->groupBy('!colName', array('colName' => 'noodle'));
     $this->assertLike('INSERT INTO bar (first, second, third, fourth) SELECT fid, 1, fid, 1 FROM foo WHERE (zoo = 3) AND (aviary = 3) GROUP BY noodle, sauce', $select->toSQL());
 }
コード例 #22
0
    /**
     * @return array
     */
    protected function prepareMembershipPermissionsFilter()
    {
        $query = '
SELECT    cm.id AS owner_id, cm.contact_id AS owner_contact, m.id AS slave_id, m.contact_id AS slave_contact, cmt.relationship_type_id AS relation_type, rel.contact_id_a, rel.contact_id_b, rel.is_permission_a_b, rel.is_permission_b_a
FROM      civicrm_membership m
LEFT JOIN civicrm_membership cm ON cm.id = m.owner_membership_id
LEFT JOIN civicrm_membership_type cmt ON cmt.id = m.membership_type_id
LEFT JOIN civicrm_relationship rel ON ( ( rel.contact_id_a = m.contact_id AND rel.contact_id_b = cm.contact_id AND rel.relationship_type_id = cmt.relationship_type_id )
                                        OR ( rel.contact_id_a = cm.contact_id AND rel.contact_id_b = m.contact_id AND rel.relationship_type_id = cmt.relationship_type_id ) )
WHERE     m.owner_membership_id IS NOT NULL AND
          ( rel.is_permission_a_b = 0 OR rel.is_permission_b_a = 0)

';
        $excludeIds = array();
        $dao = \CRM_Core_DAO::executeQuery($query, array());
        while ($dao->fetch()) {
            if ($dao->slave_contact == $dao->contact_id_a && $dao->is_permission_a_b == 0) {
                $excludeIds[] = $dao->slave_contact;
            } elseif ($dao->slave_contact == $dao->contact_id_b && $dao->is_permission_b_a == 0) {
                $excludeIds[] = $dao->slave_contact;
            }
        }
        if (!empty($excludeIds)) {
            return \CRM_Utils_SQL_Select::fragment()->where("!casContactIdField NOT IN (#excludeMemberIds)")->param(array('#excludeMemberIds' => $excludeIds));
        }
        return NULL;
    }
コード例 #23
0
 /**
  * @param \Civi\ActionSchedule\MappingInterface $mapping
  * @param \CRM_Core_DAO_ActionSchedule $actionSchedule
  * @return string
  */
 protected static function prepareMailingQuery($mapping, $actionSchedule)
 {
     $select = CRM_Utils_SQL_Select::from('civicrm_action_log reminder')->select("reminder.id as reminderID, reminder.contact_id as contactID, reminder.entity_table as entityTable, reminder.*, e.id AS entityID")->join('e', "!casMailingJoinType !casMappingEntity e ON !casEntityJoinExpr")->select("e.id as entityID, e.*")->where("reminder.action_schedule_id = #casActionScheduleId")->where("reminder.action_date_time IS NULL")->param(array('casActionScheduleId' => $actionSchedule->id, 'casMailingJoinType' => $actionSchedule->limit_to == 0 ? 'LEFT JOIN' : 'INNER JOIN', 'casMappingId' => $mapping->getId(), 'casMappingEntity' => $mapping->getEntity(), 'casEntityJoinExpr' => 'e.id = reminder.entity_id'));
     if ($actionSchedule->limit_to == 0) {
         $select->where("e.id = reminder.entity_id OR reminder.entity_table = 'civicrm_contact'");
     }
     \Civi\Core\Container::singleton()->get('dispatcher')->dispatch(\Civi\ActionSchedule\Events::MAILING_QUERY, new \Civi\ActionSchedule\Event\MailingQueryEvent($actionSchedule, $mapping, $select));
     return $select->toSQL();
 }
コード例 #24
0
 /**
  * @return \CRM_Utils_SQL_Select
  */
 protected function createQuery()
 {
     $select = \CRM_Utils_SQL_Select::from('civicrm_setting')->select('id, name, value, domain_id, contact_id, is_domain, component_id, created_date, created_id')->where('domain_id = #id', array('id' => $this->domainId));
     if ($this->contactId === NULL) {
         $select->where('is_domain = 1');
     } else {
         $select->where('contact_id = #id', array('id' => $this->contactId));
         $select->where('is_domain = 0');
     }
     return $select;
 }
コード例 #25
0
ファイル: utils.php プロジェクト: nganivet/civicrm-core
/**
 * Get function for query object api.
 *
 * This is a simple get function, but it should be usable for any kind of
 * entity. I created it to work around CRM-16036.
 *
 * @param string $dao_name
 *   Name of DAO
 * @param array $params
 *   As passed into api get function.
 * @param bool $isFillUniqueFields
 *   Do we need to ensure unique fields continue to be populated for this api? (backward compatibility).
 * @param CRM_Utils_SQL_Select|NULL $sqlFragment
 *
 * @return array
 */
function _civicrm_api3_get_using_utils_sql($dao_name, $params, $isFillUniqueFields, $sqlFragment)
{
    $dao = new $dao_name();
    $entity = _civicrm_api_get_entity_name_from_dao($dao);
    $custom_fields = _civicrm_api3_custom_fields_for_entity($entity);
    $options = _civicrm_api3_get_options_from_params($params);
    // Unset $params['options'] if they are api parameters (not options as a fieldname).
    if (!empty($params['options']) && is_array($params['options']) && array_intersect(array_keys($params['options']), array_keys($options))) {
        unset($params['options']);
    }
    $entity_field_names = _civicrm_api3_field_names(_civicrm_api3_build_fields_array($dao));
    $custom_field_names = array();
    $uniqueAliases = array();
    $getFieldsResult = civicrm_api3($entity, 'getfields', array('action' => 'get'));
    $getFieldsResult = $getFieldsResult['values'];
    foreach ($getFieldsResult as $getFieldKey => $getFieldSpec) {
        $uniqueAliases[$getFieldKey] = $getFieldSpec['name'];
        $uniqueAliases[$getFieldSpec['name']] = $getFieldSpec['name'];
    }
    // $select_fields maps column names to the field names of the result
    // values.
    $select_fields = array();
    // array with elements array('column', 'operator', 'value');
    $where_clauses = array();
    // Tables we need to join with to retrieve the custom values.
    $custom_value_tables = array();
    // ID's of custom fields that refer to a contact.
    $contact_reference_field_ids = array();
    // populate $select_fields
    $return_all_fields = empty($options['return']) || !is_array($options['return']);
    $return = $return_all_fields ? array_fill_keys($entity_field_names, 1) : $options['return'];
    // default fields
    foreach (array_keys($return) as $field_name) {
        if (!empty($uniqueAliases[$field_name]) && CRM_Core_BAO_CustomField::getKeyID($field_name) == FALSE) {
            // 'a.' is an alias for the entity table.
            $select_fields["a.{$uniqueAliases[$field_name]}"] = $uniqueAliases[$field_name];
        }
    }
    // custom fields
    foreach ($custom_fields as $cf_id => $custom_field) {
        $field_name = "custom_{$cf_id}";
        $custom_field_names[] = $field_name;
        if ($return_all_fields || !empty($options['return'][$field_name]) || !empty($options['return']['custom'])) {
            $table_name = $custom_field["table_name"];
            $column_name = $custom_field["column_name"];
            // remember that we will need to join the correct table.
            if (!in_array($table_name, $custom_value_tables)) {
                $custom_value_tables[] = $table_name;
            }
            if ($custom_field["data_type"] != "ContactReference") {
                // 'ordinary' custom field. We will select the value as custom_XX.
                $select_fields["{$table_name}.{$column_name}"] = $field_name;
            } else {
                // contact reference custom field. The ID will be stored in
                // custom_XX_id. custom_XX will contain the sort name of the
                // contact.
                $contact_reference_field_ids[] = $cf_id;
                $select_fields["{$table_name}.{$column_name}"] = $field_name . "_id";
                // We will call the contact table for the join c_XX.
                $select_fields["c_{$cf_id}.sort_name"] = $field_name;
            }
        }
    }
    if (!in_array("a.id", $select_fields)) {
        // Always select the ID.
        $select_fields["a.id"] = "id";
    }
    // build query
    $query = CRM_Utils_SQL_Select::from($dao->tableName() . " a");
    // populate $where_clauses
    foreach ($params as $key => $value) {
        $type = 'String';
        $table_name = NULL;
        $column_name = NULL;
        if (substr($key, 0, 7) == 'filter.') {
            // Legacy support for old filter syntax per the test contract.
            // (Convert the style to the later one & then deal with them).
            $filterArray = explode('.', $key);
            $value = array($filterArray[1] => $value);
            $key = 'filters';
        }
        // Legacy support for 'filter's construct.
        if ($key == 'filters') {
            foreach ($value as $filterKey => $filterValue) {
                if (substr($filterKey, -4, 4) == 'high') {
                    $key = substr($filterKey, 0, -5);
                    $value = array('<=' => $filterValue);
                }
                if (substr($filterKey, -3, 3) == 'low') {
                    $key = substr($filterKey, 0, -4);
                    $value = array('>=' => $filterValue);
                }
                if ($filterKey == 'is_current' || $filterKey == 'isCurrent') {
                    // Is current is almost worth creating as a 'sql filter' in the DAO function since several entities have the
                    // concept.
                    $todayStart = date('Ymd000000', strtotime('now'));
                    $todayEnd = date('Ymd235959', strtotime('now'));
                    $query->where(array("(a.start_date <= '{$todayStart}' OR a.start_date IS NULL) AND (a.end_date >= '{$todayEnd}' OR\n          a.end_date IS NULL)\n          AND a.is_active = 1\n        "));
                }
            }
        }
        if (array_key_exists($key, $getFieldsResult)) {
            $type = $getFieldsResult[$key]['type'];
            $key = $getFieldsResult[$key]['name'];
        }
        if ($key == _civicrm_api_get_entity_name_from_camel($entity) . '_id') {
            // The test contract enforces support of (eg) mailing_group_id if the entity is MailingGroup.
            $type = 'int';
            $key = 'id';
        }
        if (in_array($key, $entity_field_names)) {
            $table_name = 'a';
            $column_name = $key;
        } elseif (($cf_id = CRM_Core_BAO_CustomField::getKeyID($key)) != FALSE) {
            $table_name = $custom_fields[$cf_id]["table_name"];
            $column_name = $custom_fields[$cf_id]["column_name"];
            if (!in_array($table_name, $custom_value_tables)) {
                $custom_value_tables[] = $table_name;
            }
        }
        // I don't know why I had to specifically exclude 0 as a key - wouldn't the others have caught it?
        // We normally silently ignore null values passed in - if people want IS_NULL they can use acceptedSqlOperator syntax.
        if (!$table_name || empty($key) || is_null($value)) {
            // No valid filter field. This might be a chained call or something.
            // Just ignore this for the $where_clause.
            continue;
        }
        if (!is_array($value)) {
            $query->where(array("{$table_name}.{$column_name} = @value"), array("@value" => $value));
        } else {
            // We expect only one element in the array, of the form
            // "operator" => "rhs".
            $operator = CRM_Utils_Array::first(array_keys($value));
            if (!in_array($operator, CRM_Core_DAO::acceptedSQLOperators())) {
                $query->where(array("{$table_name}.{$column_name} = @value"), array("@value" => $value));
            } else {
                $query->where(CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value, $type));
            }
        }
    }
    $i = 0;
    if (!$options['is_count']) {
        foreach ($select_fields as $column => $alias) {
            ++$i;
            $query = $query->select("!column_{$i} as !alias_{$i}", array("!column_{$i}" => $column, "!alias_{$i}" => $alias));
        }
    } else {
        $query->select("count(*) as c");
    }
    // join with custom value tables
    foreach ($custom_value_tables as $table_name) {
        ++$i;
        $query = $query->join("!table_name_{$i}", "LEFT OUTER JOIN !table_name_{$i} ON !table_name_{$i}.entity_id = a.id", array("!table_name_{$i}" => $table_name));
    }
    // join with contact for contact reference fields
    foreach ($contact_reference_field_ids as $field_id) {
        ++$i;
        $query = $query->join("!contact_table_name{$i}", "LEFT OUTER JOIN civicrm_contact !contact_table_name_{$i} ON !contact_table_name_{$i}.id = !values_table_name_{$i}.!column_name_{$i}", array("!contact_table_name_{$i}" => "c_{$field_id}", "!values_table_name_{$i}" => $custom_fields[$field_id]["table_name"], "!column_name_{$i}" => $custom_fields[$field_id]["column_name"]));
    }
    foreach ($where_clauses as $clause) {
        ++$i;
        if (substr($clause[1], -4) == "NULL") {
            $query->where("!columnName_{$i} !nullThing_{$i}", array("!columnName_{$i}" => $clause[0], "!nullThing_{$i}" => $clause[1]));
        } else {
            $query->where("!columnName_{$i} !operator_{$i} @value_{$i}", array("!columnName_{$i}" => $clause[0], "!operator_{$i}" => $clause[1], "@value_{$i}" => $clause[2]));
        }
    }
    if (!empty($sqlFragment)) {
        $query->merge($sqlFragment);
    }
    // order by
    if (!empty($options['sort'])) {
        $sort_fields = array();
        foreach (explode(',', $options['sort']) as $sort_option) {
            $words = preg_split("/[\\s]+/", $sort_option);
            if (count($words) > 0 && in_array($words[0], array_values($select_fields))) {
                $tmp = $words[0];
                if (!empty($words[1]) && strtoupper($words[1]) == 'DESC') {
                    $tmp .= " DESC";
                }
                $sort_fields[] = $tmp;
            }
        }
        if (count($sort_fields) > 0) {
            $query->orderBy(implode(",", $sort_fields));
        }
    }
    // limit
    if (!empty($options['limit']) || !empty($options['offset'])) {
        $query->limit($options['limit'], $options['offset']);
    }
    $result_entities = array();
    $result_dao = CRM_Core_DAO::executeQuery($query->toSQL());
    while ($result_dao->fetch()) {
        if ($options['is_count']) {
            $result_dao->free();
            return (int) $result_dao->c;
        }
        $result_entities[$result_dao->id] = array();
        foreach ($select_fields as $column => $alias) {
            if (property_exists($result_dao, $alias) && $result_dao->{$alias} != NULL) {
                $result_entities[$result_dao->id][$alias] = $result_dao->{$alias};
            }
            // Backward compatibility on fields names.
            if ($isFillUniqueFields && !empty($getFieldsResult['values'][$column]['uniqueName'])) {
                $result_entities[$result_dao->id][$getFieldsResult['values'][$column]['uniqueName']] = $result_dao->{$alias};
            }
            foreach ($getFieldsResult as $returnName => $spec) {
                if (empty($result_entities[$result_dao->id][$returnName]) && !empty($result_entities[$result_dao->id][$spec['name']])) {
                    $result_entities[$result_dao->id][$returnName] = $result_entities[$result_dao->id][$spec['name']];
                }
            }
        }
    }
    $result_dao->free();
    return $result_entities;
}