if (!empty($params['assigneeContactIds'])) {
$assigneeContacts = array_unique(explode(',', $params['assigneeContactIds']));
}
- foreach ($assigneeContacts as $key => $value) {
+ foreach ($assigneeContacts as $value) {
$assigneeParams = [
'activity_id' => $mainActivityId,
'contact_id' => $value,
'dedupe_email_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
'hash_mailing_url' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
'auto_recipient_rebuild' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'url_tracking_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'open_tracking_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
];
public function postProcess() {
// Fetch block for a specific action
else {
$action = strtolower($action);
- $fnName = 'civicrm_api3_' . _civicrm_api_get_entity_name_from_camel($entity) . '_' . $action;
+ $fnName = 'civicrm_api3_' . CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity) . '_' . $action;
// Support the alternate "1 file per action" structure
$actionFile = "api/v3/$entity/" . ucfirst($action) . '.php';
$actionFileContents = file_get_contents("api/v3/$entity/" . ucfirst($action) . '.php', FILE_USE_INCLUDE_PATH);
/**
* Format a docblock to be a bit more readable
- * Not a proper doc parser... patches welcome :)
+ *
+ * FIXME: APIv4 uses markdown in code docs. Switch to that.
*
* @param string $text
* @return string
// Extract code blocks - save for later to skip html conversion
$code = [];
- preg_match_all('#@code(.*?)@endcode#is', $text, $code);
- $text = preg_replace('#@code.*?@endcode#is', '<pre></pre>', $text);
+ preg_match_all('#(@code|```)(.*?)(@endcode|```)#is', $text, $code);
+ $text = preg_replace('#(@code|```)(.*?)(@endcode|```)#is', '<pre></pre>', $text);
// Convert @annotations to titles
$text = preg_replace_callback(
$text = nl2br($text);
// Add unformatted code blocks back in
- if ($code && !empty($code[1])) {
- foreach ($code[1] as $block) {
+ if ($code && !empty($code[2])) {
+ foreach ($code[2] as $block) {
$text = preg_replace('#<pre></pre>#', "<pre>$block</pre>", $text, 1);
}
}
* List of component names.
* @param array $metadata
* Specification of the setting (per *.settings.php).
+ *
+ * @throws \CRM_Core_Exception.
*/
public static function onToggleComponents($oldValue, $newValue, $metadata) {
if (
$pathToCaseSampleTpl = __DIR__ . '/xml/configuration.sample/';
self::loadCaseSampleData($pathToCaseSampleTpl . 'case_sample.mysql.tpl');
if (!CRM_Case_BAO_Case::createCaseViews()) {
- $msg = ts("Could not create the MySQL views for CiviCase. Your mysql user needs to have the 'CREATE VIEW' permission");
- CRM_Core_Error::fatal($msg);
+ throw new CRM_Core_Exception(ts("Could not create the MySQL views for CiviCase. Your mysql user needs to have the 'CREATE VIEW' permission"));
}
}
}
}
else {
if ($this->_action & CRM_Core_Action::VIEW) {
- CRM_Core_Error::fatal('Contact Id is required for view action.');
+ CRM_Core_Error::statusBounce('Contact Id is required for view action.');
}
}
* @param string $caseType
* @param array $params
*
- * @return bool
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public function run($caseType, &$params) {
$xml = $this->retrieve($caseType);
if ($xml === FALSE) {
$docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
- CRM_Core_Error::fatal(ts("Configuration file could not be retrieved for case type = '%1' %2.",
+ throw new CRM_Core_Exception(ts("Configuration file could not be retrieved for case type = '%1' %2.",
[1 => $caseType, 2 => $docLink]
));
- return FALSE;
}
$xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
$xml = $this->retrieve($caseType);
if ($xml === FALSE) {
$docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
- CRM_Core_Error::fatal(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
+ throw new CRM_Core_Exception(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
[1 => $caseType, 2 => $docLink]
));
- return FALSE;
}
switch ($fieldSet) {
$params
)
) {
- CRM_Core_Error::fatal();
- return FALSE;
+ throw new CRM_Core_Exception('Unable to create case relationships');
}
}
}
* @param array $params
*
* @return bool
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public function createRelationships($relationshipTypeXML, &$params) {
list($relationshipType, $relationshipTypeName) = $this->locateNameOrLabel($relationshipTypeXML);
if ($relationshipType === FALSE) {
$docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
- CRM_Core_Error::fatal(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
+ throw new CRM_Core_Exception(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
[1 => $relationshipTypeName, 2 => $docLink]
));
- return FALSE;
}
$client = $params['clientID'];
}
if (!$this->createRelationship($relationshipParams)) {
- CRM_Core_Error::fatal();
- return FALSE;
+ throw new CRM_Core_Exception('Unable to create case relationship');
}
}
return TRUE;
if (!$activityTypeInfo) {
$docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
- CRM_Core_Error::fatal(ts('Activity type %1, found in case configuration file, is not present in the database %2',
+ throw new CRM_Core_Exception(ts('Activity type %1, found in case configuration file, is not present in the database %2',
[1 => $activityTypeName, 2 => $docLink]
));
- return FALSE;
}
$activityTypeID = $activityTypeInfo['id'];
$activity = CRM_Activity_BAO_Activity::create($activityParams);
if (!$activity) {
- CRM_Core_Error::fatal();
- return FALSE;
+ throw new CRM_Core_Exception('Unable to create Activity');
}
// create case activity record
/**
* @param $caseType
- * @param null $activityTypeName
+ * @param string|null $activityTypeName
*
* @return array|bool|mixed
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public function getMaxInstance($caseType, $activityTypeName = NULL) {
$xml = $this->retrieve($caseType);
if ($xml === FALSE) {
- CRM_Core_Error::fatal();
- return FALSE;
+ throw new CRM_Core_Exception('Unable to locate xml definition for case type ' . $caseType);
}
$activityInstances = $this->activityTypes($xml->ActivityTypes, TRUE);
$this->formatLocationBlock($value, $formatted);
}
else {
+ // @todo - this is still reachable - e.g. import with related contact info like firstname,lastname,spouse-first-name,spouse-last-name,spouse-home-phone
CRM_Core_Error::deprecatedFunctionWarning('this is not expected to be reachable now');
$this->formatContactParameters($value, $formatted);
}
if (empty($resultDAO->payment_processor_id) && CRM_Core_Permission::check('edit contributions')) {
$links = [
CRM_Core_Action::UPDATE => [
- 'name' => "<i class='crm-i fa-pencil'></i>",
+ 'name' => ts('Edit Payment'),
+ 'icon' => 'fa-pencil',
'url' => 'civicrm/payment/edit',
'class' => 'medium-popup',
'qs' => "reset=1&id=%%id%%&contribution_id=%%contribution_id%%",
* @return bool
* @throws Exception
*/
- public function loadRelatedObjects(&$input, &$ids, $loadAll = FALSE) {
+ public function loadRelatedObjects($input, &$ids, $loadAll = FALSE) {
// @todo deprecate this function - the steps should be
// 1) add additional functions like 'getRelatedMemberships'
// 2) switch all calls that refer to ->_relatedObjects to
$postProfileType = CRM_Core_BAO_UFField::getProfileType($this->_values['custom_post_id']);
}
- if (((isset($postProfileType) && $postProfileType == 'Membership') ||
- (isset($preProfileType) && $preProfileType == 'Membership')
+ if (((isset($postProfileType) && $postProfileType === 'Membership') ||
+ (isset($preProfileType) && $preProfileType === 'Membership')
) &&
!$this->_membershipBlock['is_active']
) {
- CRM_Core_Error::fatal(ts('This page includes a Profile with Membership fields - but the Membership Block is NOT enabled. Please notify the site administrator.'));
+ CRM_Core_Error::statusBounce(ts('This page includes a Profile with Membership fields - but the Membership Block is NOT enabled. Please notify the site administrator.'));
}
$pledgeBlock = CRM_Pledge_BAO_PledgeBlock::getPledgeBlock($this->_id);
!$this->_membershipBlock['is_active'] &&
!$this->_priceSetId
) {
- CRM_Core_Error::fatal(ts('The requested online contribution page is missing a required Contribution Amount section or Membership section or Price Set. Please check with the site administrator for assistance.'));
+ CRM_Core_Error::statusBounce(ts('The requested online contribution page is missing a required Contribution Amount section or Membership section or Price Set. Please check with the site administrator for assistance.'));
}
if ($this->_values['amount_block_is_active']) {
//Hence, assign the existing location type email by iterating through the params.
if ($this->_emailExists && empty($this->_params["email-{$this->_bltID}"])) {
foreach ($this->_params as $key => $val) {
- if (substr($key, 0, 6) == 'email-') {
+ if (substr($key, 0, 6) === 'email-') {
$this->assign('email', $this->_params[$key]);
break;
}
CRM_Utils_ReCAPTCHA::enableCaptchaOnForm($this);
}
+ /**
+ * Assign payment field information to the template.
+ *
+ * @throws \CRM_Core_Exception
+ * @throws \CiviCRM_API3_Exception
+ */
public function assignPaymentFields() {
//fix for CRM-3767
$isMonetary = FALSE;
// The concept of contributeMode is deprecated.
// The payment processor object can provide info about the fields it shows.
if ($isMonetary && is_a($this->_paymentProcessor['object'], 'CRM_Core_Payment')) {
- /** @var $paymentProcessorObject \CRM_Core_Payment */
+ /** @var \CRM_Core_Payment $paymentProcessorObject */
$paymentProcessorObject = $this->_paymentProcessor['object'];
$paymentFields = $paymentProcessorObject->getPaymentFormFields();
*
* @param int $id
* @param CRM_Core_Form $form
+ *
+ * @throws \CRM_Core_Exception
*/
public function buildComponentForm($id, $form) {
if (empty($id)) {
$contactID = $this->getContactID();
foreach (['soft_credit', 'on_behalf'] as $module) {
- if ($module == 'soft_credit') {
+ if ($module === 'soft_credit') {
if (empty($form->_values['honoree_profile_id'])) {
continue;
}
if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $form->_values['honoree_profile_id'], 'is_active')) {
- CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of honoree and the selected honoree profile is either disabled or not found.'));
+ CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of honoree and the selected honoree profile is either disabled or not found.'));
}
$profileContactType = CRM_Core_BAO_UFGroup::getContactType($form->_values['honoree_profile_id']);
];
$validProfile = CRM_Core_BAO_UFGroup::checkValidProfile($form->_values['honoree_profile_id'], $requiredProfileFields[$profileContactType]);
if (!$validProfile) {
- CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of honoree and the required fields of the selected honoree profile are disabled or doesn\'t exist.'));
+ CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of honoree and the required fields of the selected honoree profile are disabled or doesn\'t exist.'));
}
foreach (['honor_block_title', 'honor_block_text'] as $name) {
}
if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $form->_values['onbehalf_profile_id'], 'is_active')) {
- CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of an organization and the selected onbehalf profile is either disabled or not found.'));
+ CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of an organization and the selected onbehalf profile is either disabled or not found.'));
}
$member = CRM_Member_BAO_Membership::getMembershipBlock($form->_id);
in_array('Contribution', $onBehalfProfile)
)
) {
- CRM_Core_Error::fatal($msg);
+ CRM_Core_Error::statusBounce($msg);
}
}
}
*/
public function getTemplateFileName() {
$fileName = $this->checkTemplateFileExists();
- return $fileName ? $fileName : parent::getTemplateFileName();
+ return $fileName ?: parent::getTemplateFileName();
}
/**
/**
* Authenticate pledge user during online payment.
+ *
+ * @throws \CRM_Core_Exception
*/
public function authenticatePledgeUser() {
//get the userChecksum and contact id
}
if (!$validUser) {
- CRM_Core_Error::fatal(ts("Oops. It looks like you have an incorrect or incomplete link (URL). Please make sure you've copied the entire link, and try again. Contact the site administrator if this error persists."));
+ CRM_Core_Error::statusBounce(ts("Oops. It looks like you have an incorrect or incomplete link (URL). Please make sure you've copied the entire link, and try again. Contact the site administrator if this error persists."));
}
//check for valid pledge status.
if (!in_array($pledgeValues['status_id'], $validStatus)) {
- CRM_Core_Error::fatal(ts('Oops. You cannot make a payment for this pledge - pledge status is %1.', [1 => CRM_Utils_Array::value($pledgeValues['status_id'], $allStatus)]));
+ CRM_Core_Error::statusBounce(ts('Oops. You cannot make a payment for this pledge - pledge status is %1.', [1 => CRM_Utils_Array::value($pledgeValues['status_id'], $allStatus)]));
}
}
* In case user cancel recurring contribution,
* When we get the control back from payment gate way
* lets delete the recurring and related contribution.
+ *
+ * @throws \CRM_Core_Exception
*/
public function cancelRecurring() {
$isCancel = CRM_Utils_Request::retrieve('cancel', 'Boolean');
*
* @return bool
* Is this a separate membership payment
+ *
+ * @throws \CiviCRM_API3_Exception
+ * @throws \CRM_Core_Exception
*/
protected function buildMembershipBlock(
$cid,
$statusID = $params['contribution_status_id'] ?? NULL;
$baseIPN = new CRM_Core_Payment_BaseIPN();
- $transaction = new CRM_Core_Transaction();
-
// get the missing pieces for each contribution
$contribIDs = implode(',', $form->_contributionIds);
$details = self::getDetails($contribIDs);
);
if ($statusID == array_search('Cancelled', $contributionStatuses)) {
+ $transaction = new CRM_Core_Transaction();
$baseIPN->cancelled($objects, $transaction);
$transaction->commit();
continue;
}
elseif ($statusID == array_search('Failed', $contributionStatuses)) {
+ $transaction = new CRM_Core_Transaction();
$baseIPN->failed($objects, $transaction);
$transaction->commit();
continue;
$contributionStatuses
)
) {
- $transaction->commit();
continue;
}
$input['trxn_date'] = $params["trxn_date_{$row['contribution_id']}"] . ' ' . date('H:i:s');
$input['is_email_receipt'] = !empty($params['is_email_receipt']);
- // @todo calling baseIPN like this is a pattern in it's last gasps. Call contribute.completetransaction api.
- $baseIPN->completeTransaction($input, $ids, $objects, $transaction, FALSE);
+ // @todo calling CRM_Contribute_BAO_Contribution::completeOrder like this is a pattern in it's last gasps. Call contribute.completetransaction api.
+ CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects);
// reset template values before processing next transactions
$template->clearTemplateVars();
$urlPath,
$classes,
!empty($link['title']) ? "title='{$link['title']}' " : '',
- $link['name']
+ empty($link['icon']) ? $link['name'] : CRM_Core_Page::crmIcon($link['icon'], $link['name'], TRUE, ['title' => ''])
);
}
}
* @param int $id
* ID of the Reminder to be deleted.
*
+ * @throws CRM_Core_Exception
*/
public static function del($id) {
if ($id) {
return;
}
}
- CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+ throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
}
/**
$relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', 'Household Member of', 'id', 'name_a_b');
if (!$relTypeId) {
- CRM_Core_Error::fatal(ts("You seem to have deleted the relationship type 'Household Member of'"));
+ throw new CRM_Core_Exception(ts("You seem to have deleted the relationship type 'Household Member of'"));
}
$relParam = [
*
* @return array
* Array of $block objects.
+ * @throws CRM_Core_Exception
*/
public static function &getValues($blockName, $params) {
if (empty($params)) {
if (!isset($params['entity_table'])) {
$block->contact_id = $params['contact_id'];
if (!$block->contact_id) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Invalid Contact ID parameter passed');
}
$blocks = self::retrieveBlock($block, $blockName);
}
* @param int $componentID
* The optional component ID (so componenets can share the same name space).
* @deprecated
+ * @throws CRM_Core_Exception
*/
public static function setItem(&$data, $group, $path, $componentID = NULL) {
CRM_Core_Error::deprecatedFunctionWarning(
// CRM-11234
$lock = Civi::lockManager()->acquire("cache.{$group}_{$path}._{$componentID}");
if (!$lock->isAcquired()) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Cannot acquire database lock');
}
$table = self::getTableName();
*
* @return CRM_Core_BAO_CustomField
* The field object.
+ * @throws CRM_Core_Exception
*/
public static function getFieldObject($fieldID) {
$field = new CRM_Core_BAO_CustomField();
if (empty($fieldValues)) {
$field->id = $fieldID;
if (!$field->find(TRUE)) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Cannot find Custom Field');
}
$fieldValues = [];
* FK to civicrm_custom_field.
* @param int $newGroupID
* FK to civicrm_custom_group.
+ *
+ * @throws CRM_Core_Exception
*/
public static function moveField($fieldID, $newGroupID) {
$validation = self::_moveFieldValidate($fieldID, $newGroupID);
if (TRUE !== $validation) {
- CRM_Core_Error::fatal(implode(' ', $validation));
+ throw new CRM_Core_Exception(implode(' ', $validation));
}
$field = new CRM_Core_DAO_CustomField();
$field->id = $fieldID;
*
* @return array
* fatal is fieldID does not exists, else array of tableName, columnName
- * @throws \Exception
+ * @throws \CRM_Core_Exception
*/
public static function getTableColumnGroup($fieldID, $force = FALSE) {
$cacheKey = "CRM_Core_DAO_CustomField_CustomGroup_TableColumn_{$fieldID}";
$dao = CRM_Core_DAO::executeQuery($query, $params);
if (!$dao->fetch()) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception("Cannot find table and column information for Custom Field " . $fieldID);
}
$fieldValues = [$dao->table_name, $dao->column_name, $dao->id];
$cache->set($cacheKey, $fieldValues);
break;
default:
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Invalid HTML Type');
}
$dao = CRM_Core_DAO::executeQuery($query, $queryParams);
}
case 'File':
if (!$field['file_id']) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Missing parameter file_id');
}
// need to add/update civicrm_entity_file
return 'datetime';
default:
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Invalid Field Type');
}
}
* Array of custom values for the entity with key=>value
* pairs specified as civicrm_custom_field.id => custom value.
* Empty array if no custom values found.
+ * @throws CRM_Core_Exception
*/
public static function &getEntityValues($entityID, $entityType = NULL, $fieldIDs = NULL, $formatMultiRecordField = FALSE, $DTparams = NULL) {
if (!$entityID) {
// adding this here since an empty contact id could have serious repurcussions
// like looping forever
- CRM_Core_Error::fatal('Please file an issue with the backtrace');
+ throw new CRM_Core_Exception('Please file an issue with the backtrace');
return NULL;
}
* @return int
* $dao->id discount id of the set which matches
* the date criteria
+ * @throws CRM_Core_Exception
*/
public static function findSet($entityID, $entityTable) {
if (empty($entityID) || empty($entityTable)) {
// adding this here, to trap errors if values are not sent
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Invalid parameters passed to findSet function');
return NULL;
}
/**
* Delete a file attachment from an entity table / entity ID
- *
+ * @throws CRM_Core_Exception
*/
public static function deleteAttachment() {
$params = [];
$signer = new CRM_Utils_Signer(CRM_Core_Key::privateKey(), self::$_signableFields);
if (!$signer->validate($signature, $params)) {
- CRM_Core_Error::fatal('Request signature is invalid');
+ throw new CRM_Core_Exception('Request signature is invalid');
}
self::deleteEntityFile($params['entityTable'], $params['entityID'], NULL, $params['fileID']);
* ID of the job to be deleted.
*
* @return bool|null
+ * @throws CRM_Core_Exception
*/
public static function del($jobID) {
if (!$jobID) {
- CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+ throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
}
$dao = new CRM_Core_DAO_Job();
// make sure serialized array will fit in the 'value' column
$attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_LabelFormat', 'value');
if (strlen($this->value) > $attribute['maxlength']) {
- CRM_Core_Error::fatal(ts('Label Format does not fit in database.'));
+ throw new CRM_Core_Exception(ts('Label Format does not fit in database.'));
}
$this->save();
* Contact id.
* @param int $locationTypeId
* Id of the location to delete.
+ * @throws CRM_Core_Exception
*/
public static function deleteLocationBlocks($contactId, $locationTypeId) {
// ensure that contactId has a value
if (empty($contactId) ||
!CRM_Utils_Rule::positiveInteger($contactId)
) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Incorrect contact id parameter passed to deleteLocationBlocks');
}
if (empty($locationTypeId) ||
*
* @return array
* formatted associated array of elements
+ * @throws CRM_Core_Exception
*/
public static function formattedFields(&$params, $row = FALSE) {
$fields = [];
foreach ($value as $k => $v) {
if (in_array($v[0], $types)) {
if ($contactType && $contactType != $v[0]) {
- CRM_Core_Error::fatal(ts("Cannot have two clauses with different types: %1, %2",
+ throw new CRM_Core_Exception(ts("Cannot have two clauses with different types: %1, %2",
[1 => $contactType, 2 => $v[0]]
));
}
*
* @return int
* Group ID (null if Group ID doesn't exist)
+ * @throws CRM_Core_Exception
*/
private static function _getGid() {
if (!self::$_gid) {
self::$_gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'paper_size', 'id', 'name');
if (!self::$_gid) {
- CRM_Core_Error::fatal(ts('Paper Size Option Group not found in database.'));
+ throw new CRM_Core_Exception(ts('Paper Size Option Group not found in database.'));
}
}
return self::$_gid;
* @param array $values associative array of name/value pairs
* @param int $id
* Id of the database record (null = new record).
+ * @throws CRM_Core_Exception
*/
public function savePaperSize(&$values, $id) {
// get the Option Group ID for Paper Sizes (create one if it doesn't exist)
// make sure serialized array will fit in the 'value' column
$attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_PaperSize', 'value');
if (strlen($this->value) > $attribute['maxlength']) {
- CRM_Core_Error::fatal(ts('Paper Size does not fit in database.'));
+ throw new CRM_Core_Exception(ts('Paper Size does not fit in database.'));
}
$this->save();
*
* @param int $id
* ID of the Paper Size to be deleted.
- *
+ * @throws CRM_Core_Exception
*/
public static function del($id) {
if ($id) {
}
}
}
- CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+ throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
}
}
*
* @return int
* Group ID (null if Group ID doesn't exist)
+ * @throws CRM_Core_Exception
*/
private static function _getGid() {
if (!self::$_gid) {
self::$_gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'pdf_format', 'id', 'name');
if (!self::$_gid) {
- CRM_Core_Error::fatal(ts('PDF Format Option Group not found in database.'));
+ throw new CRM_Core_Exception(ts('PDF Format Option Group not found in database.'));
}
}
return self::$_gid;
* @param array $values associative array of name/value pairs
* @param int $id
* Id of the database record (null = new record).
+ * @throws CRM_Core_Exception
*/
public function savePdfFormat(&$values, $id = NULL) {
// get the Option Group ID for PDF Page Formats (create one if it doesn't exist)
// make sure serialized array will fit in the 'value' column
$attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_PdfFormat', 'value');
if (strlen($this->value) > $attribute['maxlength']) {
- CRM_Core_Error::fatal(ts('PDF Page Format does not fit in database.'));
+ throw new CRM_Core_Exception(ts('PDF Page Format does not fit in database.'));
}
$this->save();
*
* @param int $id
* ID of the PDF Page Format to be deleted.
- *
+ * @throws CRM_Core_Exception
*/
public static function del($id) {
if ($id) {
}
}
}
- CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+ throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
}
}
* Id of the database record.
* @param bool $is_active
* Value we want to set the is_active field.
+ * @throws CRM_Core_Exception
*/
public static function setIsActive($id, $is_active) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Cannot call setIsActive function');
}
/**
* Delete preference dates.
*
* @param int $id
+ * @throws CRM_Core_Exception
*/
public static function del($id) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Cannot call del function');
}
/**
* Generate new DAOs and along with entries in civicrm_recurring_entity table.
*
* @return array
+ * @throws CRM_Core_Exception
*/
public function generateEntities() {
self::setStatus(self::RUNNING);
}
}
if (empty($findCriteria)) {
- CRM_Core_Error::fatal("Find criteria missing to generate form. Make sure entity_id and table is set.");
+ throw new CRM_Core_Exception("Find criteria missing to generate form. Make sure entity_id and table is set.");
}
$count = 0;
*
*
* @return object
+ * @throws new CRM_Core_Exception
*/
public static function copyCreateEntity($entityTable, $fromCriteria, $newParams, $createRecurringEntity = TRUE) {
$daoName = self::$_tableDAOMapper[$entityTable];
if (!$daoName) {
- CRM_Core_Error::fatal("DAO Mapper missing for $entityTable.");
+ throw new CRM_Core_Exception("DAO Mapper missing for $entityTable.");
}
$newObject = CRM_Core_DAO::copyGeneric($daoName, $fromCriteria, $newParams);
$updateDAO = CRM_Core_DAO::cascadeUpdate($daoName, $obj->id, $entityID, $skipData);
}
else {
- CRM_Core_Error::fatal("DAO Mapper missing for $entityTable.");
+ throw new CRM_Core_Exception("DAO Mapper missing for $entityTable.");
}
}
// done with processing. lets unset static var.
foreach (self::$_linkedEntitiesInfo as $linkedTable => $linfo) {
$daoName = self::$_tableDAOMapper[$linkedTable];
if (!$daoName) {
- CRM_Core_Error::fatal("DAO Mapper missing for $linkedTable.");
+ throw new CRM_Core_Exception("DAO Mapper missing for $linkedTable.");
}
$linkedDao = new $daoName();
* @param string $columnName
* @param $length
*
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public static function alterFieldLength($customFieldID, $tableName, $columnName, $length) {
// first update the custom field tables
CRM_Core_DAO::executeQuery($sql);
}
else {
- CRM_Core_Error::fatal(ts('Could Not Find Custom Field Details for %1, %2, %3',
+ throw new CRM_Core_Exception(ts('Could Not Find Custom Field Details for %1, %2, %3',
[
1 => $tableName,
2 => $columnName,
* @param array $params
*
* @return array
+ * @throws CRM_Core_Exception
*/
public static function create($params) {
$statusPreference = new CRM_Core_BAO_StatusPreference();
$params['ignore_severity'] = CRM_Utils_Check::severityMap($params['ignore_severity']);
}
if ($params['ignore_severity'] > 7) {
- CRM_Core_Error::fatal(ts('You can not pass a severity level higher than 7.'));
+ throw new CRM_Core_Exception(ts('You can not pass a severity level higher than 7.'));
}
// If severity is now blank, you have an invalid severity string.
if (is_null($params['ignore_severity'])) {
- CRM_Core_Error::fatal(ts('Invalid string passed as severity level.'));
+ throw new CRM_Core_Exception(ts('Invalid string passed as severity level.'));
}
// Check if this StatusPreference already exists.
if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
$fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
- CRM_Core_Error::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM » Communications » FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
+ CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM » Communications » FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
}
foreach ($emailList as $emailTo) {
*
* @param $ctype
* @param bool $isLogin
+ *
+ * @throws CRM_Core_Exception
*/
public static function synchronize(&$user, $update, $uf, $ctype, $isLogin = FALSE) {
$userSystem = CRM_Core_Config::singleton()->userSystem;
$session = CRM_Core_Session::singleton();
if (!is_object($session)) {
- CRM_Core_Error::fatal('wow, session is not an object?');
+ throw new CRM_Core_Exception('wow, session is not an object?');
return;
}
* @param null $reset
*
* @return null|CRM_Core_BAO_WordReplacement
+ * @throws CRM_Core_Exception
*/
public static function getWordReplacement($reset = NULL) {
static $wordReplacement = NULL;
$wordReplacement = new CRM_Core_BAO_WordReplacement();
$wordReplacement->id = CRM_Core_Config::wordReplacementID();
if (!$wordReplacement->find(TRUE)) {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Unable to find word replacement');
}
}
return $wordReplacement;
* @param bool $force
*
* @return CRM_Core_Component_Info[]
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public static function &getComponents($force = FALSE) {
if (!isset(Civi::$statics[__CLASS__]['all']) || $force) {
require_once $infoClassFile;
$infoObject = new $infoClass($cr->name, $cr->namespace, $cr->id);
if ($infoObject->info['name'] !== $cr->name) {
- CRM_Core_Error::fatal("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
+ throw new CRM_Core_Exception("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
}
Civi::$statics[__CLASS__]['all'][$cr->name] = $infoObject;
unset($infoObject);
if (!$blockCopyofCustomValues) {
$newObject->copyCustomFields($object->id, $newObject->id);
}
- CRM_Utils_Hook::post('create', CRM_Core_DAO_AllCoreTables::getBriefName(str_replace('_BAO_', '_DAO_', $daoName)), $newObject->id, $newObject);
+ CRM_Utils_Hook::post('create', CRM_Core_DAO_AllCoreTables::getBriefName($daoName), $newObject->id, $newObject);
}
return $newObject;
* 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 class_exists($baoName) ? $baoName : $daoName;
}
+ /**
+ * Convert possibly underscore separated words to camel case with special handling for 'UF'
+ * e.g membership_payment returns MembershipPayment
+ *
+ * @param string $name
+ * @param bool $legacyV3
+ * @return string
+ */
+ public static function convertEntityNameToCamel(string $name, $legacyV3 = FALSE): string {
+ // This map only applies to APIv3
+ $map = [
+ 'acl' => 'Acl',
+ 'ACL' => 'Acl',
+ 'im' => 'Im',
+ 'IM' => 'Im',
+ ];
+ if ($legacyV3 && isset($map[$name])) {
+ return $map[$name];
+ }
+
+ $fragments = explode('_', $name);
+ foreach ($fragments as & $fragment) {
+ $fragment = ucfirst($fragment);
+ // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in without underscores)
+ if (strpos($fragment, 'Uf') === 0 && strlen($name) > 2) {
+ $fragment = 'UF' . ucfirst(substr($fragment, 2));
+ }
+ }
+ // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in underscore-separated)
+ if ($fragments[0] === 'Uf') {
+ $fragments[0] = 'UF';
+ }
+ return implode('', $fragments);
+ }
+
+ /**
+ * Convert CamelCase to snake_case, with special handling for some entity names.
+ *
+ * Eg. Activity returns activity
+ * UFGroup returns uf_group
+ * OptionValue returns option_value
+ *
+ * @param string $name
+ *
+ * @return string
+ */
+ public static function convertEntityNameToLower(string $name): string {
+ if ($name === strtolower($name)) {
+ return $name;
+ }
+ if ($name === 'PCP' || $name === 'IM' || $name === 'ACL') {
+ return strtolower($name);
+ }
+ return strtolower(ltrim(str_replace('U_F',
+ 'uf',
+ // That's CamelCase, beside an odd UFCamel that is expected as uf_camel
+ preg_replace('/(?=[A-Z])/', '_$0', $name)
+ ), '_'));
+ }
+
/**
* Get a list of all DAO classes.
*
* Ex: 'Contact'.
*/
public static function getBriefName($className) {
- return CRM_Utils_Array::value($className, array_flip(self::daoToClass()));
+ $className = self::getCanonicalClassName($className);
+ return array_search($className, self::daoToClass(), TRUE) ?: NULL;
}
/**
* @param string $className
*
* @return mixed
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public static function create($className) {
$type = self::$_classes[$className] ?? NULL;
if (!$type) {
- CRM_Core_Error::fatal("class $className not found");
+ throw new CRM_Core_Exception("class $className not found");
}
$class = self::$_prefix[$type] . $className;
$element = $this->addElement($type, $name, CRM_Utils_String::purifyHTML($label), $attributes, $extra);
if (HTML_QuickForm::isError($element)) {
- CRM_Core_Error::fatal(HTML_QuickForm::errorMessage($element));
+ CRM_Core_Error::statusBounce(HTML_QuickForm::errorMessage($element));
}
if ($inputType == 'color') {
$error = $this->addRule($name, ts('%1 is a required field.', [1 => $label]), 'required');
}
if (HTML_QuickForm::isError($error)) {
- CRM_Core_Error::fatal(HTML_QuickForm::errorMessage($element));
+ CRM_Core_Error::statusBounce(HTML_QuickForm::errorMessage($element));
}
}
public function addEntityRef($name, $label = '', $props = [], $required = FALSE) {
// Default properties
$props['api'] = CRM_Utils_Array::value('api', $props, []);
- $props['entity'] = CRM_Utils_String::convertStringToCamel(CRM_Utils_Array::value('entity', $props, 'Contact'));
+ $props['entity'] = CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel(CRM_Utils_Array::value('entity', $props, 'Contact'));
$props['class'] = ltrim(CRM_Utils_Array::value('class', $props, '') . ' crm-form-entityref');
if (array_key_exists('create', $props) && empty($props['create'])) {
$id = CRM_Utils_Request::retrieve('id', 'Int', $this);
$this->_structure = CRM_Core_I18n_SchemaStructure::columns();
if (!isset($this->_structure[$table][$field])) {
- CRM_Core_Error::fatal("$table.$field is not internationalized.");
+ CRM_Core_Error::statusBounce("$table.$field is not internationalized.");
}
$this->addElement('hidden', 'table', $table);
// validate table and field
if (!isset($this->_structure[$table][$field])) {
- CRM_Core_Error::fatal("$table.$field is not internationalized.");
+ CRM_Core_Error::statusBounce("$table.$field is not internationalized.");
}
$cols = [];
return CRM_Utils_System::redirect();
}
else {
- CRM_Core_Error::fatal('You do not have permission to execute this url');
+ CRM_Core_Error::statusBounce('You do not have permission to execute this url');
}
}
}
if (!array_key_exists('page_callback', $item)) {
CRM_Core_Error::debug('Bad item', $item);
- CRM_Core_Error::fatal(ts('Bad menu record in database'));
+ CRM_Core_Error::statusBounce(ts('Bad menu record in database'));
}
// check that we are permissioned to access this page
$object = new $item['page_callback']($title, TRUE, $mode, NULL, $addSequence);
}
else {
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Execute supplied menu action');
}
$result = $object->run($newArgs, $pageArgs);
}
* An XML document defining a list of menu items.
* @param array $menu
* An alterable list of menu items.
+ *
+ * @throws CRM_Core_Exception
*/
public static function readXML($xml, &$menu) {
$config = CRM_Core_Config::singleton();
foreach ($xml->item as $item) {
if (!(string ) $item->path) {
CRM_Core_Error::debug('i', $item);
- CRM_Core_Error::fatal();
+ throw new CRM_Core_Exception('Unable to read XML file');
}
$path = (string ) $item->path;
$menu[$path] = array();
* @param array $menu
* @param string $path
*
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
public static function fillMenuValues(&$menu, $path) {
$fieldsToPropagate = array(
return;
}
- $messages = array();
+ $messages = [];
foreach ($fieldsToPropagate as $field) {
if (!$fieldsPresent[$field]) {
$messages[] = ts("Could not find %1 in path tree",
- array(1 => $field)
+ [1 => $field]
);
}
}
- CRM_Core_Error::fatal("'$path': " . implode(', ', $messages));
+ throw new CRM_Core_Exception("'$path': " . implode(', ', $messages));
}
/**
* @param bool $condition
* Whether to display anything at all. This helps simplify code when a
* checkmark should appear if something is true.
+ * @param array $attribs
+ * Attributes to set or override on the icon element. Any standard
+ * attribute can be unset by setting the value to an empty string.
*
* @return string
* The whole bit to drop in.
*/
- public static function crmIcon($icon, $text = NULL, $condition = TRUE) {
+ public static function crmIcon($icon, $text = NULL, $condition = TRUE, $attribs = []) {
if (!$condition) {
return '';
}
+
+ // Add icon classes to any that might exist in $attribs
+ $classes = array_key_exists('class', $attribs) ? explode(' ', $attribs['class']) : [];
+ $classes[] = 'crm-i';
+ $classes[] = $icon;
+ $attribs['class'] = implode(' ', array_unique($classes));
+
+ $standardAttribs = ['aria-hidden' => 'true'];
if ($text === NULL || $text === '') {
$title = $sr = '';
}
else {
- $text = htmlspecialchars($text);
- $title = " title=\"$text\"";
+ $standardAttribs['title'] = $text;
$sr = "<span class=\"sr-only\">$text</span>";
}
- return "<i class=\"crm-i $icon\"$title></i>$sr";
+
+ // Assemble attribs
+ $attribString = '';
+ // Strip out title if $attribs specifies a blank title
+ $attribs = array_merge($standardAttribs, $attribs);
+ foreach ($attribs as $attrib => $val) {
+ if (strlen($val)) {
+ $val = htmlspecialchars($val);
+ $attribString .= " $attrib=\"$val\"";
+ }
+ }
+
+ return "<i$attribString></i>$sr";
}
}
/**
* Placeholder page which generates a redirect
*
- * @code
+ * ```
* <item>
* <path>civicrm/admin/options/case_type</path>
* <page_callback>CRM_Core_Page_Redirect</page_callback>
* <page_arguments>url=civicrm/foo/bar?whiz=bang&passthru=%%passthru%%</page_arguments>
* </item>
- * @endcoe
+ * ```
*/
class CRM_Core_Page_Redirect extends CRM_Core_Page {
*
* @return bool
*/
- public function validateData(&$input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
+ public function validateData($input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
// Check if the contribution exists
// make sure contribution exists and is valid
*
* @return bool|array
*/
- public function loadObjects(&$input, &$ids, &$objects, $required, $paymentProcessorID, $error_handling = NULL) {
+ public function loadObjects($input, &$ids, &$objects, $required, $paymentProcessorID, $error_handling = NULL) {
if (empty($error_handling)) {
// default options are that we log an error & echo it out
// note that we should refactor this error handling into error code @ some point
* @param string $permissionName
* Name of the permission we are interested in.
*
+ * @throws CRM_Core_Exception.
*/
public function permissionEmails($permissionName) {
- CRM_Core_Error::fatal("this function only works in Drupal 6 at the moment");
+ throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
}
/**
* @param string $roleName
* Name of the role we are interested in.
*
+ * @throws CRM_Core_Exception.
*/
public function roleEmails($roleName) {
- CRM_Core_Error::fatal("this function only works in Drupal 6 at the moment");
+ throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
}
/**
'fresh' => FALSE,
'context' => $context,
];
- $entity = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getCanonicalClassName($daoName));
+ $entity = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
// Custom fields are not in the schema
if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
/**
* Add a snippet of content to a region.
*
- * @code
+ * ```
* CRM_Core_Region::instance('page-header')->add(array(
* 'markup' => '<div style="color:red">Hello!</div>',
* ));
* CRM_Core_Region::instance('page-header')->add(array(
* 'callback' => 'myextension_callback_function',
* ));
- * @endcode
+ * ```
*
* Note: This function does not perform any extra encoding of markup, script code, or etc. If
* you're passing in user-data, you must clean it yourself.
/**
* Temporarily assign a list of variables.
*
- * @code
+ * ```
* $smarty->pushScope(array(
* 'first_name' => 'Alice',
* 'last_name' => 'roberts',
* ));
* $html = $smarty->fetch('view-contact.tpl');
* $smarty->popScope();
- * @endcode
+ * ```
*
* @param array $vars
* (string $name => mixed $value).
*
* Example:
*
- * @code
+ * ```
* {tsScope x=1}
* Expect {$x}==1
* {tsScope x=2}
* {/tsScope}
* Expect {$x}==1
* {/tsScope}
- * @endcode
+ * ```
*
* @param array $params
* Must define 'name'.
* @param $params
* - condition: if present and falsey, return empty
* - icon: the icon class to display instead of fa-check
+ * - anything else is passed along as attributes for the icon
*
* @param $text
* The translated text to include in the icon's title and screen-reader text.
function smarty_block_icon($params, $text, &$smarty) {
$condition = array_key_exists('condition', $params) ? $params['condition'] : 1;
$icon = $params['icon'] ?? 'fa-check';
- return CRM_Core_Page::crmIcon($icon, $text, $condition);
+ $dontPass = [
+ 'condition' => 1,
+ 'icon' => 1,
+ ];
+ return CRM_Core_Page::crmIcon($icon, $text, $condition, array_diff_key($params, $dontPass));
}
/**
* Display the CiviCRM version
*
- * @code
+ * ```
* The version is {crmVersion}.
*
* {crmVersion redact=auto assign=ver}The version is {$ver}.
- * @endcode
+ * ```
*
* @param $params
* @param $smarty
*
* To ensure that they throw exceptions, use:
*
- * @code
+ * ```
* $errorScope = CRM_Core_TemporaryErrorScope::useException();
- * @endcode
+ * ```
*
* Note that relying on this is a code-smell: it can be
* safe to temporarily switch to exception
*
* Examples:
*
- * @code
+ * ```
* // Some business logic using the helper functions
* function my_business_logic() {
* CRM_Core_Transaction::create()->run(function($tx) {
* }
* }
*
- * @endcode
+ * ```
*
* Note: As of 4.6, the transaction manager supports both reference-counting and nested
* transactions (SAVEPOINTs). In the past, it only supported reference-counting. The two cases
$fields = [];
foreach ($params as $key => $value) {
CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
- //unset the billing parameters if it is pay later mode
- //to avoid creation of billing location
- // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
- // the form & if billing fields exist we create the address, relying on the form to collect
- // only information we intend to store.
if ($this->_allowWaitlist
|| $this->_requireApproval
|| (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
|| empty($value['is_primary'])
) {
- $billingFields = [
- "email-{$this->_bltID}",
- 'billing_first_name',
- 'billing_middle_name',
- 'billing_last_name',
- "billing_street_address-{$this->_bltID}",
- "billing_city-{$this->_bltID}",
- "billing_state_province-{$this->_bltID}",
- "billing_state_province_id-{$this->_bltID}",
- "billing_postal_code-{$this->_bltID}",
- "billing_country-{$this->_bltID}",
- "billing_country_id-{$this->_bltID}",
- "address_name-{$this->_bltID}",
- ];
- foreach ($billingFields as $field) {
- unset($value[$field]);
- }
+ // This is confusing because unnecessary code around it has been removed. It is not
+ // clear why we do this / whether we should.
if (!empty($value['is_pay_later'])) {
$this->_values['params']['is_pay_later'] = TRUE;
}
// correct template IDs here
'override_verp' => TRUE,
'forward_replies' => FALSE,
- 'open_tracking' => TRUE,
- 'url_tracking' => TRUE,
+ 'open_tracking' => Civi::settings()->get('open_tracking_default'),
+ 'url_tracking' => Civi::settings()->get('url_tracking_default'),
'visibility' => 'Public Pages',
'replyto_email' => $domain_email,
'header_id' => CRM_Mailing_PseudoConstant::defaultComponent('header_id', ''),
* To ensure that PHP errors or unhandled exceptions are reported in JSON
* format, wrap this around your code. For example:
*
- * @code
+ * ```
* $errorContainer = new CRM_Queue_ErrorPolicy();
* $errorContainer->call(function() {
* ...include some files, do some work, etc...
* });
- * @endcode
+ * ```
*
* Note: Most of the code in this class is pretty generic vis-a-vis error
* handling -- except for 'reportError', whose message format is only
* different queue-providers may store the queue content in different
* ways (in memory, in SQL, or in an external service).
*
- * @code
+ * ```
* $queue = CRM_Queue_Service::singleton()->create(array(
* 'type' => 'interactive',
* 'name' => 'upgrade-tasks',
* $queue->releaseItem($item);
* }
* }
- * @endcode
+ * ```
*/
class CRM_Queue_Service {
$contributionTypes = CRM_Contribute_PseudoConstant::financialType();
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'label');
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
- $contributionPages = CRM_Contribute_PseudoConstant::contributionPage();
+ // We pass in TRUE as 2nd param so that even disabled contribution page titles are returned and replaced in the report
+ $contributionPages = CRM_Contribute_PseudoConstant::contributionPage(NULL, TRUE);
$batches = CRM_Batch_BAO_Batch::getBatches();
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
* - "match-mandatory" will generate an error
* - "match" will allow action to proceed -- thus inserting a new record
*
- * @code
+ * ```
* $result = civicrm_api('contact', 'create', array(
* 'options' => array(
* 'match' => array('last_name', 'first_name')
* 'last_name' => 'Lebowski',
* 'nick_name' => 'The Dude',
* ));
- * @endcode
+ * ```
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
* Implement the "reload" option. This option can be used with "create" to force
* the API to reload a clean copy of the entity before returning the result.
*
- * @code
+ * ```
* $clean = civicrm_api('myentity', 'create', array(
* 'options' => array(
* 'reload' => 1
* ),
* ));
- * @endcode
+ * ```
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
/**
* Call a cleanup function when the current context shuts down.
*
- * @code
+ * ```
* function doStuff() {
* $ac = CRM_Utils_AutoClean::with(function(){
* MyCleanup::doIt();
* });
* ...
* }
- * @endcode
+ * ```
*
* @param mixed $callback
* @return CRM_Utils_AutoClean
* Temporarily swap values using callback functions, and cleanup
* when the current context shuts down.
*
- * @code
+ * ```
* function doStuff() {
* $ac = CRM_Utils_AutoClean::swap('My::get', 'My::set', 'tmpValue');
* ...
* }
- * @endcode
+ * ```
*
* @param mixed $getter
* Function to lookup current value.
/**
* Capture the output from the console, copy it to a file, and pass it on.
*
- * @code
+ * ```
* $tee = CRM_Utils_ConsoleTee::create()->start();
* echo "hello world";
* $tee->stop();
* assertEquals("hello world", file_get_contents($tee->getFileName()));
- * @endCode
+ * ```
*
* Loosely speaking, it serves a similar purpose to Unix `tee`.
*
* This is a quick-and-dirty way to define a vaguely-class-ish structure. It's non-performant, abnormal,
* and not a complete OOP system. Only use for testing/mocking.
*
- * @code
+ * ```
* $object = new CRM_Utils_FakeObject(array(
* 'doIt' => function() { print "It!\n"; }
* ));
* $object->doIt();
- * @endcode
+ * ```
*/
class CRM_Utils_FakeObject {
/**
* Temporarily change a global variable.
*
- * @code
+ * ```
* $globals = CRM_Utils_GlobalStack::singleton();
* $globals->push(array(
* '_GET' => array(
* ));
* ...do stuff...
* $globals->pop();
- * @endcode
+ * ```
*
* Note: for purposes of this class, we'll refer to the array passed into
* push() as a frame.
* If omitted, default to "array('civicrm/a')" for backward compat.
* For a utility that should only be loaded on-demand, use "array()".
* For a utility that should be loaded in all pages use, "array('*')".
- * @return null
- * the return value is ignored
*
- * @code
+ * ```
* function mymod_civicrm_angularModules(&$angularModules) {
* $angularModules['myAngularModule'] = array(
* 'ext' => 'org.example.mymod',
* 'basePages' => array('civicrm/a'),
* );
* }
- * @endcode
+ * ```
+ *
+ * @return null
+ * the return value is ignored
*/
public static function angularModules(&$angularModules) {
return self::singleton()->invoke(['angularModules'], $angularModules,
*
* @param \Civi\Angular\Manager $angular
*
- * @code
+ * ```
* function example_civicrm_alterAngular($angular) {
* $changeSet = \Civi\Angular\ChangeSet::create('mychanges')
* ->alterHtml('~/crmMailing/EditMailingCtrl/2step.html', function(phpQueryObject $doc) {
* );
* $angular->add($changeSet);
* }
- * @endCode
+ * ```
*/
public static function alterAngular($angular) {
$event = \Civi\Core\Event\GenericHookEvent::create([
/**
* Modify the CiviCRM container - add new services, parameters, extensions, etc.
*
- * @code
+ * ```
* use Symfony\Component\Config\Resource\FileResource;
* use Symfony\Component\DependencyInjection\Definition;
*
* $container->addResource(new FileResource(__FILE__));
* $container->setDefinition('mysvc', new Definition('My\Class', array()));
* }
- * @endcode
+ * ```
*
* Tip: The container configuration will be compiled/cached. The default cache
* behavior is aggressive. When you first implement the hook, be sure to
* @var array
* Description of export field mapping
*
- * @code
+ * ```
* 'exampleEntityMappingName' => array(
* 'data' => array(), // placeholder; this will get filled-in during execution
* 'name' => 'CustomGroup', // per-item XML tag name
* 'idNameFields' => array('id', 'name'), // name of the (local/autogenerated) "id" and (portable) "name" columns
* 'idNameMap' => array(), // placeholder; this will get filled-in during execution
* ),
- * @endcode
+ * ```
*/
protected $_xml;
/**
* Get the value of a SQL parameter.
*
- * @code
+ * ```
* $select['cid'] = 123;
* $select->where('contact.id = #cid');
* echo $select['cid'];
- * @endCode
+ * ```
*
* @param string $offset
* @return mixed
/**
* Set the value of a SQL parameter.
*
- * @code
+ * ```
* $select['cid'] = 123;
* $select->where('contact.id = #cid');
* echo $select['cid'];
- * @endCode
+ * ```
*
* @param string $offset
* @param mixed $value
* Dear God Why Do I Have To Write This (Dumb SQL Builder)
*
* Usage:
- * @code
+ * ```
* $del = CRM_Utils_SQL_Delete::from('civicrm_activity act')
* ->where('activity_type_id = #type', array('type' => 234))
* ->where('status_id IN (#statuses)', array('statuses' => array(1,2,3))
* 'value' => $form['foo']
* ))
* echo $del->toSQL();
- * @endcode
+ * ```
*
* Design principles:
* - Portable
* xor output. The notations for input and output interpolation are a bit different,
* and they may not be mixed.
*
- * @code
+ * ```
* // Interpolate on input. Set params when using them.
* $select->where('activity_type_id = #type', array(
* 'type' => 234,
* $select
* ->where('activity_type_id = #type')
* ->param('type', 234),
- * @endcode
+ * ```
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
* Dear God Why Do I Have To Write This (Dumb SQL Builder)
*
* Usage:
- * @code
+ * ```
* $select = CRM_Utils_SQL_Select::from('civicrm_activity act')
* ->join('absence', 'inner join civicrm_activity absence on absence.id = act.source_record_id')
* ->where('activity_type_id = #type', array('type' => 234))
* 'value' => $form['foo']
* ))
* echo $select->toSQL();
- * @endcode
+ * ```
*
* Design principles:
* - Portable
* xor output. The notations for input and output interpolation are a bit different,
* and they may not be mixed.
*
- * @code
+ * ```
* // Interpolate on input. Set params when using them.
* $select->where('activity_type_id = #type', array(
* 'type' => 234,
* $select
* ->where('activity_type_id = #type')
* ->param('type', 234),
- * @endcode
+ * ```
*
* @package CRM
* @copyright CiviCRM LLC https://civicrm.org/licensing
*
* FIXME: Add TTL support?
*
- * @code
+ * ```
* $signer = new CRM_Utils_Signer('myprivatekey', array('param1','param2'));
* $params = array(
* 'param1' => 'hello',
* $token = $signer->sign($params);
* ...
* assertTrue($signer->validate($token, $params));
- * @endcode
+ * ```
*/
class CRM_Utils_Signer {
/**
}
/**
- * Convert possibly underscore separated words to camel case with special handling for 'UF'
- * e.g membership_payment returns MembershipPayment
- *
- * @param string $string
+ * Convert possibly underscore separated words to camel case.
*
+ * @param string $str
+ * @param bool $ucFirst
+ * Should the first letter be capitalized like `CamelCase` or lower like `camelCase`
* @return string
*/
- public static function convertStringToCamel($string) {
- $map = [
- 'acl' => 'Acl',
- 'ACL' => 'Acl',
- 'im' => 'Im',
- 'IM' => 'Im',
- ];
- if (isset($map[$string])) {
- return $map[$string];
- }
-
- $fragments = explode('_', $string);
- foreach ($fragments as & $fragment) {
- $fragment = ucfirst($fragment);
- // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in without underscores)
- if (strpos($fragment, 'Uf') === 0 && strlen($string) > 2) {
- $fragment = 'UF' . ucfirst(substr($fragment, 2));
- }
- }
- // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in underscore-separated)
- if ($fragments[0] === 'Uf') {
- $fragments[0] = 'UF';
- }
- return implode('', $fragments);
+ public static function convertStringToCamel($str, $ucFirst = TRUE) {
+ $fragments = explode('_', $str);
+ $camel = implode('', array_map('ucfirst', $fragments));
+ return $ucFirst ? $camel : lcfirst($camel);
}
/**
*
* For example, 'civicrm/contact/view?reset=1&cid=66' will be returned as:
*
- * @code
+ * ```
* array(
* 'path' => 'civicrm/contact/view',
* 'route' => 'civicrm.civicrm_contact_view',
* 'query' => array('reset' => '1', 'cid' => '66'),
* );
- * @endcode
+ * ```
*
* @param string $url
* The url to parse.
/**
* A central location for static variable storage.
* @var array
- * @code
+ * ```
* `Civi::$statics[__CLASS__]['foo'] = 'bar';
- * @endcode
+ * ```
*/
public static $statics = array();
* @return string
*/
public static function normalizeEntityName($entity) {
- return \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity));
+ return \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel(\CRM_Utils_String::munge($entity), TRUE);
}
/**
* The ChainSubscriber looks for API parameters which specify a nested or
* chained API call. For example:
*
- * @code
+ * ```
* $result = civicrm_api('Contact', 'create', array(
* 'version' => 3,
* 'first_name' => 'Amy',
* 'location_type_id' => 123,
* ),
* ));
- * @endcode
+ * ```
*
* The ChainSubscriber looks for any parameters of the form "api.Email.create";
* if found, it issues the nested API call (and passes some extra context --
namespace Civi\API\Subscriber;
use Civi\API\Events;
+use CRM_Core_DAO_AllCoreTables as AllCoreTables;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
*/
public function __construct($kernel, $entityName, $actions, $lookupDelegateSql, $lookupCustomFieldSql, $allowedDelegates = NULL) {
$this->kernel = $kernel;
- $this->entityName = \CRM_Utils_String::convertStringToCamel($entityName);
+ $this->entityName = AllCoreTables::convertEntityNameToCamel($entityName, TRUE);
$this->actions = $actions;
$this->lookupDelegateSql = $lookupDelegateSql;
$this->lookupCustomFieldSql = $lookupCustomFieldSql;
*/
public function onApiAuthorize(\Civi\API\Event\AuthorizeEvent $event) {
$apiRequest = $event->getApiRequest();
- if ($apiRequest['version'] == 3 && \CRM_Utils_String::convertStringToCamel($apiRequest['entity']) == $this->entityName && in_array(strtolower($apiRequest['action']), $this->actions)) {
+ if ($apiRequest['version'] == 3 && AllCoreTables::convertEntityNameToCamel($apiRequest['entity'], TRUE) == $this->entityName && in_array(strtolower($apiRequest['action']), $this->actions)) {
if (isset($apiRequest['params']['field_name'])) {
$fldIdx = \CRM_Utils_Array::index(['field_name'], $this->getCustomFields());
if (empty($fldIdx[$apiRequest['params']['field_name']])) {
* A WhitelistRule is used to determine if an API call is authorized.
* For example:
*
- * @code
+ * ```
* new WhitelistRule(array(
* 'entity' => 'Contact',
* 'actions' => array('get','getsingle'),
* 'required' => array('contact_type' => 'Organization'),
* 'fields' => array('id', 'display_name', 'sort_name', 'created_date'),
* ));
- * @endcode
+ * ```
*
* This rule would allow API requests that attempt to get contacts of type "Organization",
* but only a handful of fields ('id', 'display_name', 'sort_name', 'created_date')
*
* The basic mailing query looks a bit like this (depending on configuration):
*
- * @code
+ * ```
* SELECT reminder.id AS reminderID, reminder.contact_id as contactID, ...
* FROM `civicrm_action_log` reminder
* ... JOIN `target_entity` e ON e.id = reminder.entity_id ...
* WHERE reminder.action_schedule_id = #casActionScheduleId
- * @endcode
+ * ```
*
* Listeners may modify the query. For example, suppose we want to load
* additional fields from the related 'foo' entity:
*
- * @code
+ * ```
* $event->query->join('foo', '!casMailingJoinType civicrm_foo foo ON foo.myentity_id = e.id')
* ->select('foo.bar_value AS bar');
- * @endcode
+ * ```
*
* There are several parameters pre-set for use in queries:
* - 'casActionScheduleId'
* to fire the reminders X days after the registration date. The
* MappingInterface::createQuery() could return a query like:
*
- * @code
+ * ```
* CRM_Utils_SQL_Select::from('civicrm_participant e')
* ->join('event', 'INNER JOIN civicrm_event event ON e.event_id = event.id')
* ->where('e.is_pay_later = 1')
* ->param('casDateField', 'e.register_date')
* ->param($defaultParams)
* ...etc...
- * @endcode
+ * ```
*
* In the RELATION_FIRST phase, RecipientBuilder adds a LEFT-JOIN+WHERE to find
* participants who have *not* yet received any reminder, and filters those
* The AngularLoader stops short of bootstrapping AngularJS. You may
* need to `<div ng-app="..."></div>` or `angular.bootstrap(...)`.
*
- * @code
+ * ```
* $loader = new AngularLoader();
* $loader->setPageName('civicrm/case/a');
* $loader->setModules(array('crmApp'));
* $loader->load();
- * @endCode
+ * ```
*
* @link https://docs.angularjs.org/guide/bootstrap
*/
$permissions = \CRM_Core_Permission::getEntityActionPermissions();
// For legacy reasons the permissions are keyed by lowercase entity name
- // Note: Convert to camel & back in order to circumvent all the api3 naming oddities
- $lcentity = _civicrm_api_get_entity_name_from_camel(\CRM_Utils_String::convertStringToCamel(self::getEntityName()));
+ $lcentity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower(self::getEntityName());
// Merge permissions for this entity with the defaults
- return \CRM_Utils_Array::value($lcentity, $permissions, []) + $permissions['default'];
+ return ($permissions[$lcentity] ?? []) + $permissions['default'];
}
/**
* named "api-fields.json" which lists all the fields of
* all the API entities.
*
- * @code
+ * ```
* // Build a URL to `api-fields.json`.
* $url = \Civi::service('asset_builder')->getUrl('api-fields.json');
*
* $mimeType = 'application/json';
* $content = json_encode($fields);
* }
- * @endCode
+ * ```
*
* Assets can be parameterized. Each combination of ($asset,$params)
* will be cached separately. For example, we might want a copy of
* Simply pass the chosen entities into `getUrl()`, then update
* the definition to use `$params['entities']`, as in:
*
- * @code
+ * ```
* // Build a URL to `api-fields.json`.
* $url = \Civi::service('asset_builder')->getUrl('api-fields.json', array(
* 'entities' => array('Contact', 'Phone', 'Email', 'Address'),
* $mimeType = 'application/json';
* $content = json_encode($fields);
* }
- * @endCode
+ * ```
*
* Note: These assets are designed to hold non-sensitive data, such as
* aggregated JS or common metadata. There probably are ways to
* The event inspector is a development tool which provides metadata about events.
* It can be used for code-generators and documentation-generators.
*
- * @code
+ * ```
* $i = new CiviEventInspector();
* print_r(CRM_Utils_Array::collect('name', $i->getAll()));
- * @endCode
+ * ```
*
* An event definition includes these fields:
* - type: string, required. Ex: 'hook' or 'object'
* and methods. This requires some kind of mapping. `GenericHookEvent`
* maps each parameter to a field (using magic methods):
*
- * @code
+ * ```
* // Creating an event object.
* $event = GenericHookEvent::create(array(
* 'bar' => 'abc',
*
* // Dispatching an event.
* Civi::dispatcher()->dispatch('hook_civicrm_foo', $event);
- * @endCode
+ * ```
*
* Design Discussion:
*
* as an array, and all the returned values are merged into one big array.
* You can add and retrieve return-values using these methods:
*
- * @code
+ * ```
* $event->addReturnValues(array(...));
* foreach ($event->getReturnValues() as $retVal) { ... }
- * @endCode
+ * ```
*/
class GenericHookEvent extends \Symfony\Component\EventDispatcher\Event {
/**
* Recursively interpolate values.
*
- * @code
+ * ```
* $params = array('foo' => '@1');
* $this->interpolate($params, array('@1'=> $object))
* assert $data['foo'] == $object;
- * @endcode
+ * ```
*
* @param array $array
* Array which may or many not contain a mix of tokens.
* @return array
*/
public function checkMysqlVersion(array $db_config) {
- $min = CRM_Upgrade_Incremental_General::MIN_INSTALL_MYSQL_VER;
+ $min = \CRM_Upgrade_Incremental_General::MIN_INSTALL_MYSQL_VER;
$results = [
'title' => 'CiviCRM MySQL Version',
'severity' => $this::REQUIREMENT_OK,
/**
* Create a builder for the headless environment.
*
- * @return \Civi\Test\CiviEnvBuilder
- *
- * @code
+ * ```
* \Civi\Test::headless()->apply();
* \Civi\Test::headless()->sqlFile('ex.sql')->apply();
- * @endCode
+ * ```
+ *
+ * @return \Civi\Test\CiviEnvBuilder
*/
public static function headless() {
$civiRoot = dirname(__DIR__);
/**
* Create a builder for end-to-end testing on the live environment.
*
- * @return \Civi\Test\CiviEnvBuilder
- *
- * @code
+ * ```
* \Civi\Test::e2e()->apply();
* \Civi\Test::e2e()->install('foo.bar')->apply();
- * @endCode
+ * ```
+ *
+ * @return \Civi\Test\CiviEnvBuilder
*/
public static function e2e() {
$builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder');
* @throws \Exception
*/
public function runApi4Legacy($v3Entity, $v3Action, $v3Params = []) {
- $v4Entity = self::convertEntityNameToApi4($v3Entity);
+ $v4Entity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel($v3Entity);
$v4Action = $v3Action = strtolower($v3Action);
$v4Params = ['checkPermissions' => isset($v3Params['check_permissions']) ? (bool) $v3Params['check_permissions'] : FALSE];
$sequential = !empty($v3Params['sequential']);
// Handle single api call
list(, $chainEntity, $chainAction) = explode('.', $key);
- $lcChainEntity = \_civicrm_api_get_entity_name_from_camel($chainEntity);
- $chainEntity = self::convertEntityNameToApi4($chainEntity);
- $lcMainEntity = \_civicrm_api_get_entity_name_from_camel($mainEntity);
+ $lcChainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($chainEntity);
+ $chainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel($chainEntity);
+ $lcMainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($mainEntity);
$params = is_array($params) ? $params : [];
// Api3 expects this to be inherited
return $this->runApi4Legacy($chainEntity, $chainAction, $params);
}
- /**
- * Fix the naming differences between api3 & api4 entities.
- *
- * @param string $legacyName
- * @return string
- */
- public static function convertEntityNameToApi4($legacyName) {
- $api4Name = \CRM_Utils_String::convertStringToCamel($legacyName);
- $map = [
- 'Im' => 'IM',
- 'Acl' => 'ACL',
- ];
- return $map[$api4Name] ?? $api4Name;
- }
-
}
* This interface allows you to subscribe to hooks as part of the test.
* Simply create an eponymous hook function (e.g. `hook_civicrm_post()`).
*
- * @code
+ * ```
* class MyTest extends \PHPUnit_Framework_TestCase implements \Civi\Test\HookInterface {
* public function hook_civicrm_post($op, $objectName, $objectId, &$objectRef) {
* echo "Running hook_civicrm_post\n";
* }
* }
- * @endCode
+ * ```
*
* At time of writing, there are a few limitations in how HookInterface is handled
* by CiviTestListener:
* The TokenRegisterEvent is fired when constructing a list of available
* tokens. Listeners may register by specifying the entity/field/label for the token.
*
- * @code
+ * ```
* $ev->entity('profile')
* ->register('viewUrl', ts('Default Profile URL (View Mode)')
* ->register('editUrl', ts('Default Profile URL (Edit Mode)');
* 'field' => 'viewUrl',
* 'label' => ts('Default Profile URL (View Mode)'),
* ));
- * @endcode
+ * ```
*
* Event name: 'civi.token.list'
*/
* A TokenValueEvent is fired to convert raw query data into mergeable
* tokens. For example:
*
- * @code
+ * ```
* $event = new TokenValueEvent($myContext, 'text/html', array(
* array('contact_id' => 123),
* array('contact_id' => 456),
* (1) When setting up a job, you may specify general/baseline info.
* This is called the "context" data. Here, we create two rows:
*
- * @code
+ * ```
* $proc->addRow()->context('contact_id', 123);
* $proc->addRow()->context('contact_id', 456);
- * @endCode
+ * ```
*
* (2) When defining a token (eg `{profile.viewUrl}`), you might read the
* context-data (`contact_id`) and set the token-data (`profile => viewUrl`):
*
- * @code
+ * ```
* foreach ($proc->getRows() as $row) {
* $row->tokens('profile', [
* 'viewUrl' => 'http://example.com/profile?cid=' . urlencode($row->context['contact_id'];
* ]);
* }
- * @endCode
+ * ```
*
* The context and tokens can be accessed using either methods or attributes.
*
- * @code
+ * ```
* # Setting context data
* $row->context('contact_id', 123);
* $row->context(['contact_id' => 123]);
*
* # Reading token data
* echo $row->tokens['profile']['viewUrl'];
- * @endCode
+ * ```
*
* Note: The methods encourage a "fluent" style. They were written for PHP 5.3
* (eg before short-array syntax was supported) and are fairly flexible about
*
* @return string
* Entity name in underscore separated format.
+ *
+ * @deprecated
*/
function _civicrm_api_get_entity_name_from_camel($entity) {
- if (!$entity || $entity === strtolower($entity)) {
- return $entity;
- }
- elseif ($entity == 'PCP') {
- return 'pcp';
- }
- else {
- $entity = ltrim(strtolower(str_replace('U_F',
- 'uf',
- // That's CamelCase, beside an odd UFCamel that is expected as uf_camel
- preg_replace('/(?=[A-Z])/', '_$0', $entity)
- )), '_');
+ if (!$entity) {
+ // @todo - this should not be called when empty.
+ return '';
}
- return $entity;
+ return CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity);
}
/**
* Having a DAO object find the entity name.
*
- * @param object $bao
+ * @param CRM_Core_DAO $bao
* DAO being passed in.
*
* @return string
*/
function _civicrm_api_get_entity_name_from_dao($bao) {
- $daoName = str_replace("BAO", "DAO", get_class($bao));
- return CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
+ return CRM_Core_DAO_AllCoreTables::getBriefName(get_class($bao));
}
*
* This class allows to consume the API, either from within a module that knows civicrm already:
*
- * @code
+ * ```
* require_once('api/class.api.php');
* $api = new civicrm_api3();
- * @endcode
+ * ```
*
* or from any code on the same server as civicrm
*
- * @code
+ * ```
* require_once('/your/civi/folder/api/class.api.php');
* // the path to civicrm.settings.php
* $api = new civicrm_api3 (array('conf_path'=> '/your/path/to/your/civicrm/or/joomla/site));
- * @endcode
+ * ```
*
* or to query a remote server via the rest api
*
- * @code
+ * ```
* $api = new civicrm_api3 (array ('server' => 'http://example.org',
* 'api_key'=>'theusersecretkey',
* 'key'=>'thesitesecretkey'));
- * @endcode
+ * ```
*
* No matter how initialised and if civicrm is local or remote, you use the class the same way.
*
- * @code
+ * ```
* $api->{entity}->{action}($params);
- * @endcode
+ * ```
*
* So, to get the individual contacts:
*
- * @code
+ * ```
* if ($api->Contact->Get(array('contact_type'=>'Individual','return'=>'sort_name,current_employer')) {
* // each key of the result array is an attribute of the api
* echo "\n contacts found " . $api->count;
* } else {
* echo $api->errorMsg();
* }
- * @endcode
+ * ```
*
* Or, to create an event:
*
- * @code
+ * ```
* if ($api->Event->Create(array('title'=>'Test','event_type_id' => 1,'is_public' => 1,'start_date' => 19430429))) {
* echo "created event id:". $api->id;
* } else {
* echo $api->errorMsg();
* }
- * @endcode
+ * ```
*
* To make it easier, the Actions can either take for input an
* associative array $params, or simply an id. The following two lines
* are equivalent.
*
- * @code
+ * ```
* $api->Activity->Get (42);
* $api->Activity->Get (array('id'=>42));
- * @endcode
+ * ```
*
*
* You can also get the result like civicrm_api does, but as an object
* instead of an array (eg $entity->attribute instead of
* $entity['attribute']).
*
- * @code
+ * ```
* $result = $api->result;
* // is the json encoded result
* echo $api;
- * @endcode
+ * ```
*/
class civicrm_api3 {
* file content.
* For core fields use "entity_table", for custom fields use "field_name"
*
- * @code
+ * ```
* // Create an attachment for a core field
* $result = civicrm_api3('Attachment', 'create', array(
* 'entity_table' => 'civicrm_activity',
* ));
* $attachment = $result['values'][$result['id']];
* echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
*
- * @code
+ * ```
* // Create an attachment for a custom file field
* $result = civicrm_api3('Attachment', 'create', array(
* 'field_name' => 'custom_6',
* ));
* $attachment = $result['values'][$result['id']];
* echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
*
- * @code
+ * ```
* // Move an existing file and save as an attachment
* $result = civicrm_api3('Attachment', 'create', array(
* 'entity_table' => 'civicrm_activity',
* ));
* $attachment = $result['values'][$result['id']];
* echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
*
* Notes:
* - File content is not returned by default. One must specify 'return => content'.
*
* @param array $params
*
- * @code
+ * ```
* // REQUIRED for create:
* 'case_type_id' => int OR
* 'case_type' => str (provide one or the other)
* 'start_date' => str datestamp // defaults to: date('YmdHis')
* 'duration' => int // in minutes
* 'details' => str // html format
- * @endcode
+ * ```
*
* @throws API_Exception
* @return array
*
* @param array $params
*
- * @code
+ * ```
* //REQUIRED:
* 'id' => int
*
* //OPTIONAL
* 'move_to_trash' => bool (defaults to false)
- * @endcode
+ * ```
*
* @throws API_Exception
* @return mixed
* Expected keys are in format custom_fieldID:recordID or custom_groupName:fieldName:recordID.
*
* @example:
- * @code
+ * ```
* // entity ID. You do not need to specify entity type, we figure it out based on the fields you're using
* 'entity_id' => 123,
* // (omitting :id) inserts or updates a field in a single-valued group
* 'custom_some_group:my_field' => 'myinfo',
* // updates record ID 8 in my_other_field in multi-valued some_big_group
* 'custom_some_big_group:my_other_field:8' => 'myinfo',
- * @endcode
+ * ```
*
* @throws Exception
* @return array
*
* This api has a legacy/nonstandard signature.
* On success, the return array will be structured as follows:
- * @code
+ * ```
* array(
* "is_error" => 0,
* "version" => 3,
* "total_count" => integer
* )
* )
- * @endcode
+ * ```
*
* On failure, the return array will be structured as follows:
- * @code
+ * ```
* array(
* 'is_error' => 1,
* 'error_message' = string,
* 'error_data' = mixed or undefined
* )
- * @endcode
+ * ```
*
* @param array $params
* Input parameters:
$params['forward_replies']['api.default'] = FALSE;
$params['auto_responder']['api.default'] = FALSE;
- $params['open_tracking']['api.default'] = TRUE;
- $params['url_tracking']['api.default'] = TRUE;
+ $params['open_tracking']['api.default'] = Civi::settings()->get('open_tracking_default');
+ $params['url_tracking']['api.default'] = Civi::settings()->get('url_tracking_default');
$params['header_id']['api.default'] = CRM_Mailing_PseudoConstant::defaultComponent('Header', '');
$params['footer_id']['api.default'] = CRM_Mailing_PseudoConstant::defaultComponent('Footer', '');
* @return array
*/
function _civicrm_api3_basic_get($bao_name, $params, $returnAsSuccess = TRUE, $entity = "", $sql = NULL, $uniqueFields = FALSE) {
- $entity = $entity ?: CRM_Core_DAO_AllCoreTables::getBriefName(str_replace('_BAO_', '_DAO_', $bao_name));
+ $entity = $entity ?: CRM_Core_DAO_AllCoreTables::getBriefName($bao_name);
$options = _civicrm_api3_get_options_from_params($params);
$query = new \Civi\API\Api3SelectQuery($entity, CRM_Utils_Array::value('check_permissions', $params, FALSE));
if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
return $fieldName;
}
- if ($fieldName == _civicrm_api_get_entity_name_from_camel($entity) . '_id') {
+ if ($fieldName === (CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity) . '_id')) {
return 'id';
}
$result = civicrm_api($entity, 'getfields', [
'description' => ts('Allow sending email from the logged in contact\'s email address.'),
'help_text' => 'CiviCRM allows you to send email from the domain from email addresses and the logged in contact id addresses by default. Disable this if you only want to allow the domain from addresses to be used.',
],
+ 'url_tracking_default' => [
+ 'group_name' => 'Mailing Preferences',
+ 'group' => 'mailing',
+ 'name' => 'url_tracking_default',
+ 'type' => 'Boolean',
+ 'html_type' => 'checkbox',
+ 'quick_form_type' => 'CheckBox',
+ 'default' => '1',
+ 'title' => ts('Enable click-through tracking by default'),
+ 'is_domain' => 1,
+ 'is_contact' => 0,
+ 'description' => ts('If checked, mailings will have click-through tracking enabled by default.'),
+ 'help_text' => NULL,
+ ],
+ 'open_tracking_default' => [
+ 'group_name' => 'Mailing Preferences',
+ 'group' => 'mailing',
+ 'name' => 'open_tracking_default',
+ 'type' => 'Boolean',
+ 'html_type' => 'checkbox',
+ 'quick_form_type' => 'CheckBox',
+ 'default' => '1',
+ 'title' => ts('Enable open tracking by default'),
+ 'is_domain' => 1,
+ 'is_contact' => 0,
+ 'description' => ts('If checked, mailings will have open tracking enabled by default.'),
+ 'help_text' => NULL,
+ ],
];
CRM.$(function($) {
var mailSetting = $("input[name='outBound_option']:checked").val( );
- var archiveWarning = "{/literal}{ts escape='js'}WARNING: You are switching from a testing mode (Redirect to Database) to a live mode. Check Mailings > Archived Mailings, and delete any test mailings that are not in Completed status prior to running the mailing cron job for the first time. This will ensure that test mailings are not actually sent out.{/ts}{literal}"
+ var archiveWarning = "{/literal}{ts escape='js'}WARNING: You are switching from a testing mode (Redirect to Database) to a live mode. Check Mailings > Archived Mailings, and delete any test mailings that are not in Completed status prior to running the mailing cron job for the first time. This will ensure that test mailings are not actually sent out.{/ts}{literal}";
showHideMailOptions( $("input[name='outBound_option']:checked").val( ) ) ;
<tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
<td>
{if $index GT 1}
- <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>
+ <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}hide field or section{/ts}{/icon}</a>
{/if}
</td>
<td> {$form.order_bys.$index.column.html}</td>
{/section}
</table>
<div id="optionFieldLink" class="add-remove-link">
- <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another column{/ts}</a>
+ <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another column{/ts}</a>
</div>
<script type="text/javascript">
if (interview.errors[error]) errorList = errorList + '<li>' + interview.errors[error] + '</li>';
}
if ( errorList ) {
- var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red"></i> {/literal}{ts}Please correct the following errors in the survey fields below:{/ts}{literal}<ul>' + errorList + '</ul>';
+ var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red" aria-hidden="true"></i> {/literal}{ts}Please correct the following errors in the survey fields below:{/ts}{literal}<ul>' + errorList + '</ul>';
CRM.$('#responseErrors').show( ).html(allErrors);
}
}
var caseUrl = destUrl + selectedCaseId + '&cid=' + contactId + context;
var statusMsg = {/literal}'{ts escape='js' 1='%1'}Activity has been filed to %1 case.{/ts}'{literal};
- CRM.alert(ts(statusMsg, {1: '<a href="' + caseUrl + '">' + caseTitle + '</a>'}), '{/literal}{ts escape="js"}Saved{/ts}{literal}', 'success');
+ CRM.alert(ts(statusMsg, {1: '<a href="' + caseUrl + '">' + CRM._.escape(caseTitle) + '</a>'}), '{/literal}{ts escape="js"}Saved{/ts}{literal}', 'success');
CRM.refreshParent(a);
}
}
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*}
-{capture assign=expandIconURL}<img src="{$config->resourceBase}i/TreePlus.gif" alt="{ts}open section{/ts}"/>{/capture}
{strip}
<table class="case-selector-{$list} crm-ajax-table" data-page-length='10'>
<thead>
{section name=rowLoop start=1 loop=6}
{assign var=index value=$smarty.section.rowLoop.index}
<tr id="discount_{$index}" class=" crm-event-manage-fee-form-block-discount_{$index} {if $index GT 1 AND empty( $form.discount_name[$index].value) } hiddenElement {/if} form-item {cycle values="odd-row,even-row"}">
- <td>{if $index GT 1} <a onclick="showHideDiscountRow('discount_{$index}', false, {$index}); return false;" name="discount_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>{/if}
+ <td>{if $index GT 1} <a onclick="showHideDiscountRow('discount_{$index}', false, {$index}); return false;" name="discount_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}remove discount set{/ts}{/icon}</span></a>{/if}
</td>
<td class="crm-event-manage-fee-form-block-discount_name"> {$form.discount_name.$index.html}</td>
<td class="crm-event-manage-fee-form-block-discount_start_date"> {$form.discount_start_date.$index.html} </td>
{/section}
</table>
<div id="discountLink" class="add-remove-link">
- <a onclick="showHideDiscountRow( 'discount', true);return false;" id="discountLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another discount set{/ts}</a>
+ <a onclick="showHideDiscountRow( 'discount', true);return false;" id="discountLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another discount set{/ts}</a>
</div>
{$form._qf_Fee_submit.html}
</div><div class="spacer"></div>
<div id="comment" style="display:none">
<table class="form-layout">
- <tr class="crm-mailing-forward-form-block-forward_comment"><td><a href="#" onclick="cj('#comment').hide(); cj('#comment_show').show(); return false;"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}close section{/ts}"/></a>
+ <tr class="crm-mailing-forward-form-block-forward_comment"><td><a href="#" onclick="cj('#comment').hide(); cj('#comment_show').show(); return false;">{icon icon="fa-caret-down action-icon"}{ts}close section{/ts}{/icon}</a>
<label>{$form.forward_comment.label}</label></td>
<td>{$form.forward_comment.html}<br /><br />
{$form.html_comment.html}<br /></td>
(function($) {
$('#groups').val('').change(function() {
CRM.confirm({
- message: ts({/literal}'{ts escape='js' 1='<em>%1</em>'}Add all contacts to %1 group?{/ts}'{literal}, {1: $('option:selected', '#groups').text()})
+ message: ts({/literal}'{ts escape='js' 1='<em>%1</em>'}Add all contacts to %1 group?{/ts}'{literal}, {1: CRM._.escape($('option:selected', '#groups').text())})
})
.on({
'crmConfirm:yes': function() {
<tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
<td>
{if $index GT 1}
- <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>
+ <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}remove sort by column{/ts}{/icon}</a>
{/if}
</td>
<td> {$form.order_bys.$index.column.html}</td>
{/section}
</table>
<div id="optionFieldLink" class="add-remove-link">
- <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another column{/ts}</a>
+ <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another column{/ts}</a>
</div>
<script type="text/javascript">
var showRows = new Array({$showBlocks});
--- /dev/null
+<?php
+
+/**
+ * @group headless
+ */
+class CRM_Activity_Page_AJAXTest extends CiviUnitTestCase {
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->loadAllFixtures();
+
+ CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
+
+ $this->loggedInUser = $this->createLoggedInUser();
+ $this->target = $this->individualCreate();
+ }
+
+ /**
+ * Test the underlying function that implements file-on-case.
+ *
+ * The UI is a quickform but it's only realized as a popup ajax form that
+ * doesn't have its own postProcess. Instead the values are ultimately
+ * passed to the function this test is testing. So there's no form or ajax
+ * being tested here, just the final act of filing the activity.
+ */
+ public function testConvertToCaseActivity() {
+ $activity = $this->callAPISuccess('Activity', 'create', [
+ 'source_contact_id' => $this->loggedInUser,
+ 'activity_type_id' => 'Meeting',
+ 'subject' => 'test file on case',
+ 'status_id' => 'Completed',
+ 'target_id' => $this->target,
+ ]);
+
+ $case = $this->callAPISuccess('Case', 'create', [
+ 'contact_id' => $this->target,
+ 'case_type_id' => 'housing_support',
+ 'subject' => 'Needs housing',
+ ]);
+
+ $params = [
+ 'activityID' => $activity['id'],
+ 'caseID' => $case['id'],
+ 'mode' => 'file',
+ 'targetContactIds' => $this->target,
+ ];
+ $result = CRM_Activity_Page_AJAX::_convertToCaseActivity($params);
+
+ $this->assertEmpty($result['error_msg']);
+ $newActivityId = $result['newId'];
+
+ $caseActivities = $this->callAPISuccess('Activity', 'get', [
+ 'case_id' => $case['id'],
+ ])['values'];
+ $this->assertEquals('test file on case', $caseActivities[$newActivityId]['subject']);
+ // This should be a different physical activity, not the same db record as the original.
+ $this->assertNotEquals($activity['id'], $caseActivities[$newActivityId]['id']);
+ }
+
+}
$this->assertFalse(CRM_Core_DAO_AllCoreTables::isCoreTable('civicrm_invalid_table'), 'civicrm_invalid_table should NOT be a core table');
}
+ public function testGetBriefName() {
+ $this->assertEquals('Contact', CRM_Core_DAO_AllCoreTables::getBriefName('CRM_Contact_BAO_Contact'));
+ $this->assertEquals('Contact', CRM_Core_DAO_AllCoreTables::getBriefName('CRM_Contact_DAO_Contact'));
+ }
+
}
--- /dev/null
+<?php
+
+/**
+ * Class CRM_Core_PageTest
+ * @group headless
+ */
+class CRM_Core_PageTest extends CiviUnitTestCase {
+
+ /**
+ * Test data for testMakeIcons
+ *
+ * @return array
+ */
+ public function iconTestData() {
+ // first item is icon, text, condition, and attribs, second is expected markup
+ return [
+ [
+ '<i aria-hidden="true" title="We have a winner" class="crm-i fa-trophy"></i><span class="sr-only">We have a winner</span>',
+ ['fa-trophy', 'We have a winner', TRUE, []],
+ '{icon icon="fa-trophy"}We have a winner{/icon}',
+ ],
+ [
+ '',
+ ['fa-trophy', 'We have a winner', 0, []],
+ '{icon icon="fa-trophy" condition=0}We have a winner{/icon}',
+ ],
+ [
+ '<i aria-hidden="true" title="Favorite" class="action-icon test-icon crm-i fa-heart"></i><span class="sr-only">Favorite</span>',
+ ['fa-heart', 'Favorite', TRUE, ['class' => 'action-icon test-icon']],
+ '{icon icon="fa-heart" class="action-icon test-icon"}Favorite{/icon}',
+ ],
+ [
+ '<i aria-hidden="true" title="I "choo-choo" choose you" class="crm-i fa-train"></i><span class="sr-only">I "choo-choo" choose you</span>',
+ ['fa-train', 'I "choo-choo" choose you', TRUE, []],
+ '{icon icon="fa-train"}I "choo-choo" choose you{/icon}',
+ ],
+ [
+ '<i aria-hidden="true" class="crm-i fa-trash"></i><span class="sr-only">Trash</span>',
+ ['fa-trash', 'Trash', TRUE, ['title' => '']],
+ '{icon icon="fa-trash" title=""}Trash{/icon}',
+ ],
+ [
+ '<i title="It\'s bedtime" class="crm-i fa-bed"></i><span class="sr-only">It\'s bedtime</span>',
+ ['fa-bed', "It's bedtime", TRUE, ['aria-hidden' => '']],
+ // Ye olde Smarty 2 doesn't support hyphenated function parameters
+ ],
+ [
+ '<i aria-hidden="true" class="crm-i fa-snowflake-o"></i>',
+ ['fa-snowflake-o', NULL, TRUE, []],
+ '{icon icon="fa-snowflake-o"}{/icon}',
+ ],
+ ];
+ }
+
+ /**
+ * Test that icons are formed properly
+ *
+ * @param string $expectedMarkup
+ * @param array $params
+ * @param string $smartyFunc
+ * @dataProvider iconTestData
+ */
+ public function testMakeIcons($expectedMarkup, $params, $smartyFunc = '') {
+ list($icon, $text, $condition, $attribs) = $params;
+ $this->assertEquals($expectedMarkup, CRM_Core_Page::crmIcon($icon, $text, $condition, $attribs));
+ if (!empty($smartyFunc)) {
+ $smarty = CRM_Core_Smarty::singleton();
+ $actual = $smarty->fetch('string:' . $smartyFunc);
+ $this->assertEquals($expectedMarkup, $actual, "Process input=[$smartyFunc]");
+ }
+ }
+
+}
*/
class CRM_Logging_SchemaTest extends CiviUnitTestCase {
+ protected $databaseVersion;
+
public function setUp() {
+ $this->databaseVersion = CRM_Utils_SQL::getDatabaseVersion();
parent::setUp();
}
public function tearDown() {
$schema = new CRM_Logging_Schema();
$schema->disableLogging();
+ $this->databaseVersion = NULL;
parent::tearDown();
$this->quickCleanup(['civicrm_contact'], TRUE);
$schema->dropAllLogTables();
$this->assertEquals('int', $ci['test_id']['DATA_TYPE']);
$this->assertEquals('NO', $ci['test_id']['IS_NULLABLE']);
$this->assertEquals('auto_increment', $ci['test_id']['EXTRA']);
- $this->assertEquals('10', $ci['test_id']['LENGTH']);
+ if (!$this->isMySQL8()) {
+ $this->assertEquals('10', $ci['test_id']['LENGTH']);
+ }
$this->assertEquals('varchar', $ci['test_varchar']['DATA_TYPE']);
$this->assertEquals('42', $ci['test_varchar']['LENGTH']);
$this->assertEquals('int', $ci['test_integer']['DATA_TYPE']);
- $this->assertEquals('8', $ci['test_integer']['LENGTH']);
+ if (!$this->isMySQL8()) {
+ $this->assertEquals('8', $ci['test_integer']['LENGTH']);
+ }
$this->assertEquals('YES', $ci['test_integer']['IS_NULLABLE']);
$this->assertEquals('decimal', $ci['test_decimal']['DATA_TYPE']);
$schema->fixSchemaDifferences();
$ci = \Civi::$statics['CRM_Logging_Schema']['columnSpecs'];
// length should increase
- $this->assertEquals(6, $ci['log_civicrm_test_length_change']['test_integer']['LENGTH']);
+ if (!$this->isMySQL8()) {
+ $this->assertEquals(6, $ci['log_civicrm_test_length_change']['test_integer']['LENGTH']);
+ }
$this->assertEquals('22,2', $ci['log_civicrm_test_length_change']['test_decimal']['LENGTH']);
CRM_Core_DAO::executeQuery(
"ALTER TABLE civicrm_test_length_change
$schema->fixSchemaDifferences();
$ci = \Civi::$statics['CRM_Logging_Schema']['columnSpecs'];
// length should not decrease
- $this->assertEquals(6, $ci['log_civicrm_test_length_change']['test_integer']['LENGTH']);
+ if (!$this->isMySQL8()) {
+ $this->assertEquals(6, $ci['log_civicrm_test_length_change']['test_integer']['LENGTH']);
+ }
$this->assertEquals('22,2', $ci['log_civicrm_test_length_change']['test_decimal']['LENGTH']);
}
$this->assertEquals("'A','B','C','D'", $ci['civicrm_test_enum_change']['test_enum']['ENUM_VALUES']);
}
+ /**
+ * Determine if we are running on MySQL 8 version 8.0.19 or later.
+ *
+ * @return bool
+ */
+ protected function isMySQL8() {
+ return (bool) (version_compare($this->databaseVersion, '8.0.19', '>=') && stripos($this->databaseVersion, 'mariadb') === FALSE);
+ }
+
}
return TRUE;
}
- public function fromToData() {
+ /**
+ * Used by testGetFromTo
+ */
+ private function fromToData() {
$cases = [];
// Absolute dates
- $cases[] = ['20170901000000', '20170913235959', 0, '09/01/2017', '09/13/2017'];
+ $cases['absolute'] = [
+ 'expectedFrom' => '20170901000000',
+ 'expectedTo' => '20170913235959',
+ 'relative' => 0,
+ 'from' => '09/01/2017',
+ 'to' => '09/13/2017',
+ ];
// "Today" relative date filter
$date = new DateTime();
- $expectedFrom = $date->format('Ymd') . '000000';
- $expectedTo = $date->format('Ymd') . '235959';
- $cases[] = [$expectedFrom, $expectedTo, 'this.day', '', ''];
+ $cases['today'] = [
+ 'expectedFrom' => $date->format('Ymd') . '000000',
+ 'expectedTo' => $date->format('Ymd') . '235959',
+ 'relative' => 'this.day',
+ 'from' => '',
+ 'to' => '',
+ ];
// "yesterday" relative date filter
$date = new DateTime();
$date->sub(new DateInterval('P1D'));
- $expectedFrom = $date->format('Ymd') . '000000';
- $expectedTo = $date->format('Ymd') . '235959';
- $cases[] = [$expectedFrom, $expectedTo, 'previous.day', '', ''];
+ $cases['yesterday'] = [
+ 'expectedFrom' => $date->format('Ymd') . '000000',
+ 'expectedTo' => $date->format('Ymd') . '235959',
+ 'relative' => 'previous.day',
+ 'from' => '',
+ 'to' => '',
+ ];
return $cases;
}
/**
* Test that getFromTo returns the correct dates.
- *
- * @dataProvider fromToData
- *
- * @param string $expectedFrom
- * @param string $expectedTo
- * @param string $relative
- * @param string $from
- * @param string $to
*/
- public function testGetFromTo($expectedFrom, $expectedTo, $relative, $from, $to) {
- $obj = new CRM_Report_Form();
- if (date('Hi') === '0000') {
- $this->markTestIncomplete('The date might have changed since the dataprovider was called. Skip to avoid flakiness');
+ public function testGetFromTo() {
+ $cases = $this->fromToData();
+ foreach ($cases as $caseDescription => $case) {
+ $obj = new CRM_Report_Form();
+ list($calculatedFrom, $calculatedTo) = $obj->getFromTo($case['relative'], $case['from'], $case['to']);
+ $this->assertEquals([$case['expectedFrom'], $case['expectedTo']], [$calculatedFrom, $calculatedTo], "fail on data set '{$caseDescription}'. Local php time is " . date('Y-m-d H:i:s') . ' and mysql time is ' . CRM_Core_DAO::singleValueQuery('SELECT NOW()'));
}
- list($calculatedFrom, $calculatedTo) = $obj->getFromTo($relative, $from, $to);
- $this->assertEquals([$expectedFrom, $expectedTo], [$calculatedFrom, $calculatedTo], "fail on data set [ $relative , $from , $to ]. Local php time is " . date('Y-m-d H:i:s') . ' and mysql time is ' . CRM_Core_DAO::singleValueQuery('SELECT NOW()'));
}
}
return TRUE;
}
- public function fromToData() {
+ /**
+ * Used by testGetFromTo
+ */
+ private function fromToData() {
$cases = [];
// Absolute dates
- $cases[] = ['20170901000000', '20170913235959', 0, '09/01/2017', '09/13/2017'];
+ $cases['absolute'] = [
+ 'expectedFrom' => '20170901000000',
+ 'expectedTo' => '20170913235959',
+ 'relative' => 0,
+ 'from' => '09/01/2017',
+ 'to' => '09/13/2017',
+ ];
// "Today" relative date filter
$date = new DateTime();
- $expectedFrom = $date->format('Ymd') . '000000';
- $expectedTo = $date->format('Ymd') . '235959';
- $cases[] = [$expectedFrom, $expectedTo, 'this.day', '', ''];
+ $cases['today'] = [
+ 'expectedFrom' => $date->format('Ymd') . '000000',
+ 'expectedTo' => $date->format('Ymd') . '235959',
+ 'relative' => 'this.day',
+ 'from' => '',
+ 'to' => '',
+ ];
// "yesterday" relative date filter
$date = new DateTime();
$date->sub(new DateInterval('P1D'));
- $expectedFrom = $date->format('Ymd') . '000000';
- $expectedTo = $date->format('Ymd') . '235959';
- $cases[] = [$expectedFrom, $expectedTo, 'previous.day', '', ''];
+ $cases['yesterday'] = [
+ 'expectedFrom' => $date->format('Ymd') . '000000',
+ 'expectedTo' => $date->format('Ymd') . '235959',
+ 'relative' => 'previous.day',
+ 'from' => '',
+ 'to' => '',
+ ];
return $cases;
}
/**
* Test that getFromTo returns the correct dates.
- *
- * @dataProvider fromToData
- * @param $expectedFrom
- * @param $expectedTo
- * @param $relative
- * @param $from
- * @param $to
*/
- public function testGetFromTo($expectedFrom, $expectedTo, $relative, $from, $to) {
- $obj = new CRM_Utils_Date();
- list($calculatedFrom, $calculatedTo) = $obj->getFromTo($relative, $from, $to);
- $this->assertEquals($expectedFrom, $calculatedFrom);
- $this->assertEquals($expectedTo, $calculatedTo);
+ public function testGetFromTo() {
+ $cases = $this->fromToData();
+ foreach ($cases as $caseDescription => $case) {
+ $obj = new CRM_Utils_Date();
+ list($calculatedFrom, $calculatedTo) = $obj->getFromTo($case['relative'], $case['from'], $case['to']);
+ $this->assertEquals($case['expectedFrom'], $calculatedFrom, "Expected From failed for case $caseDescription");
+ $this->assertEquals($case['expectedTo'], $calculatedTo, "Expected To failed for case $caseDescription");
+ }
}
/**
* Create a batch of external API calls which can
* be executed concurrently.
*
- * @code
+ * ```
* $calls = $this->createExternalAPI()
* ->addCall('Contact', 'get', ...)
* ->addCall('Contact', 'get', ...)
* ...
* ->run()
* ->getResults();
- * @endcode
+ * ```
*
* @return \Civi\API\ExternalBatch
* @throws PHPUnit_Framework_SkippedTestError