/** * Create a query to find references to a particular record * * @param CRM_Core_DAO $targetDao the instance for which we want references * @return CRM_Core_DAO a query-handle (like the result of CRM_Core_DAO::executeQuery) */ public function findReferences($targetDao) { $refColumn = $this->getReferenceKey(); $targetColumn = $this->getTargetKey(); $params = array(1 => array($targetDao->{$targetColumn}, 'String'), 2 => array($targetDao::getTableName(), 'String')); $sql = <<<EOS SELECT id FROM {$this->getReferenceTable()} WHERE {$refColumn} = %1 AND {$this->getTypeColumn()} = %2 EOS; $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($this->getReferenceTable()); $result = CRM_Core_DAO::executeQuery($sql, $params, TRUE, $daoName); return $result; }
/** * Determine the standard URL for viewing or editing the specified link. * * This function delegates the decision-making to (a) the hook system and * (b) the BAO system. * * @param array $crudLinkSpec * With keys:. * - action: int, CRM_Core_Action::UPDATE or CRM_Core_Action::VIEW [default: VIEW] * - entity_table: string, eg "civicrm_contact" * - entity_id: int * @return array|NULL * NULL if unavailable, or an array. array has keys: * - path: string * - query: array * - title: string * - url: string */ public static function createDefaultCrudLink($crudLinkSpec) { $crudLinkSpec['action'] = CRM_Utils_Array::value('action', $crudLinkSpec, CRM_Core_Action::VIEW); $daoClass = CRM_Core_DAO_AllCoreTables::getClassForTable($crudLinkSpec['entity_table']); if (!$daoClass) { return NULL; } $baoClass = str_replace('_DAO_', '_BAO_', $daoClass); if (!class_exists($baoClass)) { return NULL; } $bao = new $baoClass(); $bao->id = $crudLinkSpec['entity_id']; if (!$bao->find(TRUE)) { return NULL; } $link = array(); CRM_Utils_Hook::crudLink($crudLinkSpec, $bao, $link); if (empty($link) && is_callable(array($bao, 'createDefaultCrudLink'))) { $link = $bao->createDefaultCrudLink($crudLinkSpec); } if (!empty($link)) { if (!isset($link['url'])) { $link['url'] = self::url($link['path'], $link['query'], TRUE, NULL, FALSE); } return $link; } return NULL; }
/** * Apply common settings to entityRef fields. * * @param array $field * @param string $table */ private function setEntityRefDefaults(&$field, $table) { $field['attributes'] = $field['attributes'] ? $field['attributes'] : array(); $field['attributes'] += array('entity' => CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getClassForTable($table)), 'multiple' => TRUE, 'placeholder' => ts('- select -')); }
/** * @param $entityTable */ public static function preProcess($entityTable) { self::$_entityId = (int) CRM_Utils_Request::retrieve('id', 'Positive'); self::$_entityTable = $entityTable; if (self::$_entityId && $entityTable) { $checkParentExistsForThisId = CRM_Core_BAO_RecurringEntity::getParentFor(self::$_entityId, $entityTable); if ($checkParentExistsForThisId) { self::$_hasParent = TRUE; self::$_parentEntityId = $checkParentExistsForThisId; self::$_scheduleReminderDetails = CRM_Core_BAO_RecurringEntity::getReminderDetailsByEntityId($checkParentExistsForThisId, $entityTable); } else { self::$_parentEntityId = self::$_entityId; self::$_scheduleReminderDetails = CRM_Core_BAO_RecurringEntity::getReminderDetailsByEntityId(self::$_entityId, $entityTable); } if (property_exists(self::$_scheduleReminderDetails, 'id')) { self::$_scheduleReminderID = self::$_scheduleReminderDetails->id; } } CRM_Core_OptionValue::getValues(array('name' => $entityTable . '_repeat_exclude_dates_' . self::$_parentEntityId), $optionValue); $excludeOptionValues = array(); if (!empty($optionValue)) { foreach ($optionValue as $key => $val) { $excludeOptionValues[$val['value']] = substr(CRM_Utils_Date::mysqlToIso($val['value']), 0, 10); } self::$_excludeDateInfo = $excludeOptionValues; } // Assign variables $entityType = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getClassForTable($entityTable)); $tpl = CRM_Core_Smarty::singleton(); $tpl->assign('recurringEntityType', ts($entityType)); $tpl->assign('currentEntityId', self::$_entityId); $tpl->assign('entityTable', self::$_entityTable); $tpl->assign('scheduleReminderId', self::$_scheduleReminderID); $tpl->assign('hasParent', self::$_hasParent); }
/** * Low-level option getter, rarely accessed directly. * NOTE: Rather than calling this function directly use CRM_*_BAO_*::buildOptions() * * @param String $daoName * @param String $fieldName * @param Array $params * - name string name of the option group * - flip boolean results are return in id => label format if false * if true, the results are reversed * - grouping boolean if true, return the value in 'grouping' column (currently unsupported for tables other than option_value) * - localize boolean if true, localize the results before returning * - condition string|array add condition(s) to the sql query - will be concatenated using 'AND' * - keyColumn string the column to use for 'id' * - labelColumn string the column to use for 'label' * - orderColumn string the column to use for sorting, defaults to 'weight' column if one exists, else defaults to labelColumn * - onlyActive boolean return only the action option values * - fresh boolean ignore cache entries and go back to DB * @param String $context: Context string * * @return Array on success, FALSE on error. * * @static */ public static function get($daoName, $fieldName, $params = array(), $context = NULL) { CRM_Core_DAO::buildOptionsContext($context); $flip = !empty($params['flip']); // Merge params with defaults $params += array('grouping' => FALSE, 'localize' => FALSE, 'onlyActive' => $context == 'validate' || $context == 'get' ? FALSE : TRUE, 'fresh' => FALSE); // Custom fields are not in the schema if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) { $customField = new CRM_Core_DAO_CustomField(); $customField->id = (int) substr($fieldName, 7); $customField->find(TRUE); $options = FALSE; if (!empty($customField->option_group_id)) { $options = CRM_Core_OptionGroup::valuesByID($customField->option_group_id, $flip, $params['grouping'], $params['localize'], CRM_Utils_Array::value('labelColumn', $params, 'label'), $params['onlyActive'], $params['fresh']); } else { if ($customField->data_type === 'StateProvince') { $options = self::stateProvince(); } elseif ($customField->data_type === 'Country') { $options = $context == 'validate' ? self::countryIsoCode() : self::country(); } elseif ($customField->data_type === 'Boolean') { $options = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No')); } $options = $options && $flip ? array_flip($options) : $options; } if ($options !== FALSE) { CRM_Utils_Hook::customFieldOptions($customField->id, $options, FALSE); } $customField->free(); return $options; } // Core field: load schema $dao = new $daoName(); $fields = $dao->fields(); $fieldKeys = $dao->fieldKeys(); $dao->free(); // Support "unique names" as well as sql names $fieldKey = $fieldName; if (empty($fields[$fieldKey])) { $fieldKey = CRM_Utils_Array::value($fieldName, $fieldKeys); } // If neither worked then this field doesn't exist. Return false. if (empty($fields[$fieldKey])) { return FALSE; } $fieldSpec = $fields[$fieldKey]; // If the field is an enum, explode the enum definition and return the array. if (isset($fieldSpec['enumValues'])) { // use of a space after the comma is inconsistent in xml $enumStr = str_replace(', ', ',', $fieldSpec['enumValues']); $output = explode(',', $enumStr); return array_combine($output, $output); } elseif (!empty($fieldSpec['pseudoconstant'])) { $pseudoconstant = $fieldSpec['pseudoconstant']; // Merge params with schema defaults $params += array('condition' => CRM_Utils_Array::value('condition', $pseudoconstant, array()), 'keyColumn' => CRM_Utils_Array::value('keyColumn', $pseudoconstant), 'labelColumn' => CRM_Utils_Array::value('labelColumn', $pseudoconstant)); // Fetch option group from option_value table if (!empty($pseudoconstant['optionGroupName'])) { if ($context == 'validate') { $params['labelColumn'] = 'name'; } // Call our generic fn for retrieving from the option_value table return CRM_Core_OptionGroup::values($pseudoconstant['optionGroupName'], $flip, $params['grouping'], $params['localize'], $params['condition'] ? ' AND ' . implode(' AND ', (array) $params['condition']) : NULL, $params['labelColumn'] ? $params['labelColumn'] : 'label', $params['onlyActive'], $params['fresh'], $params['keyColumn'] ? $params['keyColumn'] : 'value'); } // Fetch options from other tables if (!empty($pseudoconstant['table'])) { // Normalize params so the serialized cache string will be consistent. CRM_Utils_Array::remove($params, 'flip', 'fresh'); ksort($params); $cacheKey = $daoName . $fieldName . serialize($params); // Retrieve cached options if (isset(self::$cache[$cacheKey]) && empty($params['fresh'])) { $output = self::$cache[$cacheKey]; } else { $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($pseudoconstant['table']); if (!class_exists($daoName)) { return FALSE; } // Get list of fields for the option table $dao = new $daoName(); $availableFields = array_keys($dao->fieldKeys()); $dao->free(); $select = "SELECT %1 AS id, %2 AS label"; $from = "FROM %3"; $wheres = array(); $order = "ORDER BY %2"; // Use machine name instead of label in validate context if ($context == 'validate') { if (!empty($pseudoconstant['nameColumn'])) { $params['labelColumn'] = $pseudoconstant['nameColumn']; } elseif (in_array('name', $availableFields)) { $params['labelColumn'] = 'name'; } } // Condition param can be passed as an sql clause string or an array of clauses if (!empty($params['condition'])) { $wheres[] = implode(' AND ', (array) $params['condition']); } // onlyActive param will automatically filter on common flags if (!empty($params['onlyActive'])) { foreach (array('is_active' => 1, 'is_deleted' => 0, 'is_test' => 0) as $flag => $val) { if (in_array($flag, $availableFields)) { $wheres[] = "{$flag} = {$val}"; } } } // Filter domain specific options if (in_array('domain_id', $availableFields)) { $wheres[] = 'domain_id = ' . CRM_Core_Config::domainID(); } $queryParams = array(1 => array($params['keyColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES), 2 => array($params['labelColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES), 3 => array($pseudoconstant['table'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES)); // Add orderColumn param if (!empty($params['orderColumn'])) { $queryParams[4] = array($params['orderColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES); $order = "ORDER BY %4"; } elseif (isset($params['orderColumn']) && $params['orderColumn'] === FALSE) { $order = ''; } elseif (in_array('weight', $availableFields)) { $order = "ORDER BY weight"; } $output = array(); $query = "{$select} {$from}"; if ($wheres) { $query .= " WHERE " . implode($wheres, ' AND '); } $query .= ' ' . $order; $dao = CRM_Core_DAO::executeQuery($query, $queryParams); while ($dao->fetch()) { $output[$dao->id] = $dao->label; } $dao->free(); // Localize results if (!empty($params['localize']) || $pseudoconstant['table'] == 'civicrm_country' || $pseudoconstant['table'] == 'civicrm_state_province') { $I18nParams = array(); if ($pseudoconstant['table'] == 'civicrm_country') { $I18nParams['context'] = 'country'; } if ($pseudoconstant['table'] == 'civicrm_state_province') { $I18nParams['context'] = 'province'; } $i18n = CRM_Core_I18n::singleton(); $i18n->localizeArray($output, $I18nParams); // Maintain sort by label if ($order == "ORDER BY %2") { CRM_Utils_Array::asort($output); } } self::$cache[$cacheKey] = $output; } return $flip ? array_flip($output) : $output; } } elseif (CRM_Utils_Array::value('type', $fieldSpec) === CRM_Utils_Type::T_BOOLEAN) { $output = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No')); return $flip ? array_flip($output) : $output; } // If we're still here, it's an error. Return FALSE. return FALSE; }
/** * Lookup the admin page at which a field's option list can be edited * @param $fieldSpec * @return string|null */ static function getOptionEditUrl($fieldSpec) { // If it's an option group, that's easy if (!empty($fieldSpec['pseudoconstant']['optionGroupName'])) { return 'civicrm/admin/options/' . $fieldSpec['pseudoconstant']['optionGroupName']; } elseif (!empty($fieldSpec['pseudoconstant']['table'])) { $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($fieldSpec['pseudoconstant']['table']); if (!$daoName) { return NULL; } // We don't have good mapping so have to do a bit of guesswork from the menu list(, $parent, , $child) = explode('_', $daoName); $sql = "SELECT path FROM civicrm_menu\n WHERE page_callback LIKE '%CRM_Admin_Page_{$child}%' OR page_callback LIKE '%CRM_{$parent}_Page_{$child}%'\n ORDER BY page_callback\n LIMIT 1"; return CRM_Core_Dao::singleValueQuery($sql); } return NULL; }
/** * Find all records which refer to this entity. * * @return array * Array of objects referencing this */ public function findReferences() { $links = self::getReferencesToTable(static::getTableName()); $occurrences = array(); foreach ($links as $refSpec) { /** @var $refSpec CRM_Core_Reference_Interface */ $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($refSpec->getReferenceTable()); $result = $refSpec->findReferences($this); if ($result) { while ($result->fetch()) { $obj = new $daoName(); $obj->id = $result->id; $occurrences[] = $obj; } } } return $occurrences; }
/** * Find all records which refer to this entity. * * @return array of objects referencing this */ function findReferences() { $links = self::getReferencesToTable(static::getTableName()); $occurrences = array(); foreach ($links as $refSpec) { $refColumn = $refSpec->getReferenceKey(); $targetColumn = $refSpec->getTargetKey(); $params = array(1 => array($this->{$targetColumn}, 'String')); $sql = <<<EOS SELECT id FROM {$refSpec->getReferenceTable()} WHERE {$refColumn} = %1 EOS; if ($refSpec->isGeneric()) { $params[2] = array(static::getTableName(), 'String'); $sql .= <<<EOS AND {$refSpec->getTypeColumn()} = %2 EOS; } $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($refSpec->getReferenceTable()); $result = self::executeQuery($sql, $params, TRUE, $daoName); while ($result->fetch()) { $obj = new $daoName(); $obj->id = $result->id; $occurrences[] = $obj; } } return $occurrences; }
/** * Revert changes in the array of diffs in $this->diffs. */ public function revert() { // get custom data tables, columns and types $ctypes = array(); $dao = CRM_Core_DAO::executeQuery('SELECT table_name, column_name, data_type FROM civicrm_custom_group cg JOIN civicrm_custom_field cf ON (cf.custom_group_id = cg.id)'); while ($dao->fetch()) { if (!isset($ctypes[$dao->table_name])) { $ctypes[$dao->table_name] = array('entity_id' => 'Integer'); } $ctypes[$dao->table_name][$dao->column_name] = $dao->data_type; } $diffs = $this->diffs; $deletes = array(); $reverts = array(); foreach ($diffs as $table => $changes) { foreach ($changes as $change) { switch ($change['action']) { case 'Insert': if (!isset($deletes[$table])) { $deletes[$table] = array(); } $deletes[$table][] = $change['id']; break; case 'Delete': case 'Update': if (!isset($reverts[$table])) { $reverts[$table] = array(); } if (!isset($reverts[$table][$change['id']])) { $reverts[$table][$change['id']] = array('log_action' => $change['action']); } $reverts[$table][$change['id']][$change['field']] = $change['from']; break; } } } // revert inserts by deleting foreach ($deletes as $table => $ids) { CRM_Core_DAO::executeQuery("DELETE FROM `{$table}` WHERE id IN (" . implode(', ', array_unique($ids)) . ')'); } // revert updates by updating to previous values foreach ($reverts as $table => $row) { switch (TRUE) { // DAO-based tables case ($tableDAO = CRM_Core_DAO_AllCoreTables::getClassForTable($table)) != FALSE: $dao = new $tableDAO(); foreach ($row as $id => $changes) { $dao->id = $id; foreach ($changes as $field => $value) { if ($field == 'log_action') { continue; } if (empty($value) and $value !== 0 and $value !== '0') { $value = 'null'; } $dao->{$field} = $value; } $changes['log_action'] == 'Delete' ? $dao->insert() : $dao->update(); $dao->reset(); } break; // custom data tables // custom data tables case in_array($table, array_keys($ctypes)): foreach ($row as $id => $changes) { $inserts = array('id' => '%1'); $updates = array(); $params = array(1 => array($id, 'Integer')); $counter = 2; foreach ($changes as $field => $value) { // don’t try reverting a field that’s no longer there if (!isset($ctypes[$table][$field])) { continue; } $fldVal = "%{$counter}"; switch ($ctypes[$table][$field]) { case 'Date': $value = substr(CRM_Utils_Date::isoToMysql($value), 0, 8); break; case 'Timestamp': $value = CRM_Utils_Date::isoToMysql($value); break; case 'Boolean': if ($value === '') { $fldVal = 'DEFAULT'; } } $inserts[$field] = "%{$counter}"; $updates[] = "{$field} = {$fldVal}"; if ($fldVal != 'DEFAULT') { $params[$counter] = array($value, $ctypes[$table][$field]); } $counter++; } if ($changes['log_action'] == 'Delete') { $sql = "INSERT INTO `{$table}` (" . implode(', ', array_keys($inserts)) . ') VALUES (' . implode(', ', $inserts) . ')'; } else { $sql = "UPDATE `{$table}` SET " . implode(', ', $updates) . ' WHERE id = %1'; } CRM_Core_DAO::executeQuery($sql, $params); } break; } } // CRM-7353: if nothing altered civicrm_contact, touch it; this will // make sure there’s an entry in log_civicrm_contact for this revert if (empty($diffs['civicrm_contact'])) { $query = "\n SELECT id FROM `{$this->db}`.log_civicrm_contact\n WHERE log_conn_id = %1 AND log_date BETWEEN DATE_SUB(%2, INTERVAL 10 SECOND) AND DATE_ADD(%2, INTERVAL 10 SECOND)\n ORDER BY log_date DESC LIMIT 1\n "; $params = array(1 => array($this->log_conn_id, 'String'), 2 => array($this->log_date, 'String')); $cid = CRM_Core_DAO::singleValueQuery($query, $params); if (!$cid) { return; } $dao = new CRM_Contact_DAO_Contact(); $dao->id = $cid; if ($dao->find(TRUE)) { // CRM-8102: MySQL can’t parse its own dates $dao->birth_date = CRM_Utils_Date::isoToMysql($dao->birth_date); $dao->deceased_date = CRM_Utils_Date::isoToMysql($dao->deceased_date); $dao->save(); } } }
/** * Generates acl clauses suitable for adding to WHERE or ON when doing an api.get for this entity * * Return format is in the form of fieldname => clauses starting with an operator. e.g.: * @code * array( * 'location_type_id' => array('IS NOT NULL', 'IN (1,2,3)') * ) * @endcode * * Note that all array keys must be actual field names in this entity. Use subqueries to filter on other tables e.g. custom values. * * @return array */ public function addSelectWhereClause() { $clauses = array(); $fields = $this->fields(); foreach ($fields as $fieldName => $field) { // Clause for contact-related entities like Email, Relationship, etc. if (strpos($fieldName, 'contact_id') === 0 && CRM_Utils_Array::value('FKClassName', $field) == 'CRM_Contact_DAO_Contact') { $clauses[$fieldName] = CRM_Utils_SQL::mergeSubquery('Contact'); } // Clause for an entity_table/entity_id combo if ($fieldName == 'entity_id' && isset($fields['entity_table'])) { $relatedClauses = array(); $relatedEntities = $this->buildOptions('entity_table', 'get'); foreach ((array) $relatedEntities as $table => $ent) { if (!empty($ent)) { $ent = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getClassForTable($table)); $subquery = CRM_Utils_SQL::mergeSubquery($ent); if ($subquery) { $relatedClauses[] = "(entity_table = '{$table}' AND entity_id " . implode(' AND entity_id ', $subquery) . ")"; } else { $relatedClauses[] = "(entity_table = '{$table}')"; } } } if ($relatedClauses) { $clauses['id'] = 'IN (SELECT id FROM `' . $this->tableName() . '` WHERE (' . implode(') OR (', $relatedClauses) . '))'; } } } CRM_Utils_Hook::selectWhereClause($this, $clauses); return $clauses; }
/** * @param string $entityTable * The target entity table (e.g. "civicrm_mailing" or "civicrm_activity"). * @return string|NULL * The target entity name (e.g. "Mailing" or "Activity"). */ public function getDelegatedEntityName($entityTable) { if ($this->allowedDelegates === NULL || in_array($entityTable, $this->allowedDelegates)) { $className = \CRM_Core_DAO_AllCoreTables::getClassForTable($entityTable); if ($className) { $entityName = \CRM_Core_DAO_AllCoreTables::getBriefName($className); if ($entityName) { return $entityName; } } } return NULL; }
/** * @param $table * * @return array */ public function titlesAndValuesForTable($table) { // static caches for subsequent calls with the same $table static $titles = array(); static $values = array(); if (!isset($titles[$table]) or !isset($values[$table])) { if (($tableDAO = CRM_Core_DAO_AllCoreTables::getClassForTable($table)) != FALSE) { // FIXME: these should be populated with pseudo constants as they // were at the time of logging rather than their current values // FIXME: Use *_BAO:buildOptions() method rather than pseudoconstants & fetch programmatically $values[$table] = array('contribution_page_id' => CRM_Contribute_PseudoConstant::contributionPage(), 'contribution_status_id' => CRM_Contribute_PseudoConstant::contributionStatus(), 'financial_type_id' => CRM_Contribute_PseudoConstant::financialType(), 'country_id' => CRM_Core_PseudoConstant::country(), 'gender_id' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'), 'location_type_id' => CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id'), 'payment_instrument_id' => CRM_Contribute_PseudoConstant::paymentInstrument(), 'phone_type_id' => CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id'), 'preferred_communication_method' => CRM_Contact_BAO_Contact::buildOptions('preferred_communication_method'), 'preferred_language' => CRM_Contact_BAO_Contact::buildOptions('preferred_language'), 'prefix_id' => CRM_Contact_BAO_Contact::buildOptions('prefix_id'), 'provider_id' => CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id'), 'state_province_id' => CRM_Core_PseudoConstant::stateProvince(), 'suffix_id' => CRM_Contact_BAO_Contact::buildOptions('suffix_id'), 'website_type_id' => CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id'), 'activity_type_id' => CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE), 'case_type_id' => CRM_Case_PseudoConstant::caseType('title', FALSE), 'priority_id' => CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id')); // for columns that appear in more than 1 table switch ($table) { case 'civicrm_case': $values[$table]['status_id'] = CRM_Case_PseudoConstant::caseStatus('label', FALSE); break; case 'civicrm_activity': $values[$table]['status_id'] = CRM_Core_PseudoConstant::activityStatus(); break; } $dao = new $tableDAO(); foreach ($dao->fields() as $field) { $titles[$table][$field['name']] = CRM_Utils_Array::value('title', $field); if ($field['type'] == CRM_Utils_Type::T_BOOLEAN) { $values[$table][$field['name']] = array('0' => ts('false'), '1' => ts('true')); } } } elseif (substr($table, 0, 14) == 'civicrm_value_') { list($titles[$table], $values[$table]) = $this->titlesAndValuesForCustomDataTable($table); } else { $titles[$table] = $values[$table] = array(); } } return array($titles[$table], $values[$table]); }