public function buildQuickForm() {
$htmlFields = array();
foreach ($this->_settings as $setting => $group) {
+ // @todo - remove this whole loop! The parent form does this - it's just because of the werid handling
+ // of $htmlFields for this form that needs to be unwound that we have it atm.
+ // The 'basicform' has been contaminated with processing $htlFields
+ // to cater to this form - probably due to the way invoicing settings were handled as
+ // an array not a bunch of keys.
$settingMetaData = civicrm_api3('setting', 'getfields', array('name' => $setting));
$props = $settingMetaData['values'][$setting];
if (isset($props['quick_form_type'])) {
$add = 'add' . $props['quick_form_type'];
if ($add == 'addElement') {
if (in_array($props['html_type'], array('checkbox', 'textarea'))) {
- $this->add($props['html_type'],
- $setting,
- $props['title']
- );
}
else {
if ($props['html_type'] == 'select') {
$props['option_values'] = array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::$functionName();
}
}
- $this->$add(
- $props['html_type'],
- $setting,
- ts($props['title']),
- CRM_Utils_Array::value($props['html_type'] == 'select' ? 'option_values' : 'html_attributes', $props, array()),
- $props['html_type'] == 'select' ? CRM_Utils_Array::value('html_attributes', $props) : NULL
- );
}
}
- elseif ($add == 'addMonthDay') {
- $this->add('date', $setting, ts($props['title']), CRM_Core_SelectValues::date(NULL, 'M d'));
- }
- elseif ($add == 'addDate') {
- $this->addDate($setting, ts($props['title']), FALSE, array('formatType' => $props['type']));
- }
- else {
- $this->$add($setting, ts($props['title']));
- }
}
$htmlFields[$setting] = ts($props['description']);
}
unset($params['qfKey']);
unset($params['entryURL']);
Civi::settings()->set('contribution_invoice_settings', $params);
- Civi::settings()->set('update_contribution_on_membership_type_change',
- CRM_Utils_Array::value('update_contribution_on_membership_type_change', $params)
- );
// to set default value for 'Invoices / Credit Notes' checkbox on display preferences
$values = CRM_Core_BAO_Setting::getItem("CiviCRM Preferences");
'contact_smart_group_display' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'advanced_search_options' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'user_dashboard_options' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+ 'activity_assignee_notification' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+ 'activity_assignee_notification_ics' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'preserve_activity_tab_filter' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+ 'ajaxPopupsEnabled' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'display_name_format' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'sort_name_format' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
);
'title' => ts('Editing Contacts'),
'weight' => 3,
),
- 'activity_assignee_notification' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Notify Activity Assignees'),
- 'weight' => 5,
- ),
- 'activity_assignee_notification_ics' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Include ICal Invite to Activity Assignees'),
- 'weight' => 6,
- ),
'contact_ajax_check_similar' => array(
'title' => ts('Check for Similar Contacts'),
'weight' => 8,
'html_type' => NULL,
),
-
'editor_id' => array(
'html_type' => NULL,
'weight' => 12,
),
- 'ajaxPopupsEnabled' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable Popup Forms'),
- 'weight' => 13,
- ),
'do_not_notify_assignees_for' => array(
'html_type' => 'select',
'option_values' => $optionValues,
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2018
- * $Id: Display.php 36505 2011-10-03 14:19:56Z lobo $
- *
*/
/**
- * This class generates form components for the component preferences
- *
+ * This class generates form components for the maling component preferences.
*/
class CRM_Admin_Form_Preferences_Mailing extends CRM_Admin_Form_Preferences {
- public function preProcess() {
- CRM_Utils_System::setTitle(ts('CiviMail Component Settings'));
- $this->_varNames = array(
- CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME => array(
- 'profile_double_optin' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable Double Opt-in for Profile Group(s) field'),
- 'weight' => 1,
- 'description' => ts('When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.'),
- ),
- 'profile_add_to_group_double_optin' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable Double Opt-in for Profiles which use the "Add to Group" setting'),
- 'weight' => 2,
- 'description' => ts('When CiviMail is enabled and a profile uses the "Add to Group" setting, users who complete the profile form will receive a confirmation email. They must respond (opt-in) before they are added to the group.'),
- ),
- 'track_civimail_replies' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Track replies using VERP in Reply-To header'),
- 'weight' => 3,
- 'description' => ts('If checked, mailings will default to tracking replies using VERP-ed Reply-To.'),
- ),
- 'civimail_workflow' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable workflow support for CiviMail'),
- 'weight' => 4,
- 'description' => ts('Drupal-only. Rules module must be enabled (beta feature - use with caution).'),
- ),
- 'civimail_multiple_bulk_emails' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable multiple bulk email address for a contact.'),
- 'weight' => 5,
- 'description' => ts('CiviMail will deliver a copy of the email to each bulk email listed for the contact.'),
- ),
- 'civimail_server_wide_lock' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable global server wide lock for CiviMail'),
- 'weight' => 6,
- 'description' => NULL,
- ),
- 'include_message_id' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable CiviMail to generate Message-ID header'),
- 'weight' => 7,
- 'description' => NULL,
- ),
- 'write_activity_record' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable CiviMail to create activities on delivery'),
- 'weight' => 8,
- 'description' => NULL,
- ),
- 'disable_mandatory_tokens_check' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Disable check for mandatory tokens'),
- 'weight' => 9,
- 'description' => ts('Don\'t check for presence of mandatory tokens (domain address; unsubscribe/opt-out) before sending mailings. WARNING: Mandatory tokens are a safe-guard which facilitate compliance with the US CAN-SPAM Act. They should only be disabled if your organization adopts other mechanisms for compliance or if your organization is not subject to CAN-SPAM.'),
- ),
- 'dedupe_email_default' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('CiviMail dedupes e-mail addresses by default'),
- 'weight' => 10,
- 'description' => NULL,
- ),
- 'hash_mailing_url' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Hashed Mailing URL\'s'),
- 'weight' => 11,
- 'description' => ts('If enabled, a randomized hash key will be used to reference the mailing URL in the mailing.viewUrl token, instead of the mailing ID'),
- ),
- 'auto_recipient_rebuild' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable automatic CiviMail recipient count display'),
- 'weight' => 12,
- 'description' => ts('Enable this setting to rebuild recipient list automatically during composing mail. Disable will allow you to rebuild recipient manually.'),
- ),
- ),
- );
- parent::preProcess();
- }
+ protected $_settings = [
+ 'profile_double_optin' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'profile_add_to_group_double_optin' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'track_civimail_replies' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'civimail_workflow' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'civimail_multiple_bulk_emails' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'civimail_server_wide_lock' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'include_message_id' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'write_activity_record' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ 'disable_mandatory_tokens_check' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+ '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,
+ ];
public function postProcess() {
- // check if mailing tab is enabled, if not prompt user to enable the tab if "write_activity_record" is disabled
$params = $this->controller->exportValues($this->_name);
if (empty($params['write_activity_record'])) {
+ // @todo use the setting onToggle & add an action rather than have specific form handling.
+ // see logging setting for eg.
$existingViewOptions = Civi::settings()->get('contact_view_options');
$displayValue = CRM_Core_OptionGroup::getValue('contact_view_options', 'CiviMail', 'name');
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2018
- * $Id: Display.php 36505 2011-10-03 14:19:56Z lobo $
- *
*/
/**
- * This class generates form components for multi site preferences
- *
+ * This class generates form components for multi site preferences.
*/
class CRM_Admin_Form_Preferences_Multisite extends CRM_Admin_Form_Preferences {
- public function preProcess() {
- $msDoc = CRM_Utils_System::docURL2('Multi Site Installation', NULL, NULL, NULL, NULL, "wiki");
- CRM_Utils_System::setTitle(ts('Multi Site Settings'));
- $this->_varNames = array(
- CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME => array(
- 'is_enabled' => array(
- 'html_type' => 'checkbox',
- 'title' => ts('Enable Multi Site Configuration'),
- 'weight' => 1,
- 'description' => ts('Make CiviCRM aware of multiple domains. You should configure a domain group if enabled') . ' ' . $msDoc,
- ),
- /** Remove this checkbox until some one knows what this setting does
- * 'uniq_email_per_site' => array(
- * 'html_type' => 'checkbox',
- * 'title' => ts('Ensure multi sites have a unique email per site'),
- * 'weight' => 2,
- * 'description' => NULL,
- * ),
- */
- 'domain_group_id' => array(
- 'html_type' => 'entity_reference',
- 'title' => ts('Domain Group'),
- 'weight' => 3,
- 'options' => array('entity' => 'group', 'select' => array('minimumInputLength' => 0)),
- 'description' => ts('Contacts created on this site are added to this group'),
- ),
- /** Remove this checkbox until some one knows what this setting does
- * 'event_price_set_domain_id' => array(
- * 'html_type' => 'text',
- * 'title' => ts('Domain for event price sets'),
- * 'weight' => 4,
- * 'description' => NULL,
- * ),
- */
- ),
- );
- parent::preProcess();
- }
+ protected $_settings = [
+ 'is_enabled' => CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME,
+ 'domain_group_id' => CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME,
+ ];
}
* @return array
*/
protected function getSettingsToSetByMetadata($params) {
- return array_intersect_key($params, $this->_settings);
+ $setValues = array_intersect_key($params, $this->_settings);
+ // Checkboxes will be unset rather than empty so we need to add them back in.
+ // Handle quickform hateability just once, right here right now.
+ $unsetValues = array_diff_key($this->_settings, $params);
+ foreach ($unsetValues as $key => $unsetValue) {
+ if ($this->getQuickFormType($this->getSettingMetadata($key)) === 'CheckBox') {
+ $setValues[$key] = [$key => 0];
+ }
+ }
+ return $setValues;
}
/**
$this->includesReadOnlyFields = TRUE;
}
+ if (isset($props['help_link'])) {
+ // Set both the value in this loop & the outer value as we assign both to the template while we deprecate the $descriptions assignment.
+ $settingMetaData[$setting]['description'] = $props['description'] .= ' ' . CRM_Utils_System::docURL2($props['help_link']['page'], NULL, NULL, NULL, NULL, $props['help_link']['resource']);
+
+ }
$add = 'add' . $quickFormType;
if ($add == 'addElement') {
$this->$add(
elseif ($add == 'addMonthDay') {
$this->add('date', $setting, ts($props['title']), CRM_Core_SelectValues::date(NULL, 'M d'));
}
+ elseif ($add === 'addEntityRef') {
+ $this->$add($setting, ts($props['title']), $props['entity_reference_options']);
+ }
else {
$this->$add($setting, ts($props['title']), $options);
}
* @return string
*/
protected function getQuickFormType($spec) {
- if (isset($spec['quick_form_type'])) {
+ if (isset($spec['quick_form_type']) &&
+ !($spec['quick_form_type'] === 'Element' && !empty($spec['html_type']))) {
return $spec['quick_form_type'];
}
$mapping = [
'radio' => 'Radio',
'select' => 'Select',
'textarea' => 'Element',
+ 'entity_reference' => 'EntityRef',
];
return $mapping[$spec['html_type']];
}
if ($this->getQuickFormType($spec) === 'CheckBoxes') {
$this->_defaults[$setting] = array_fill_keys($this->_defaults[$setting], 1);
}
+ if ($this->getQuickFormType($spec) === 'CheckBox') {
+ $this->_defaults[$setting] = [$setting => $this->_defaults[$setting]];
+ }
}
}
if ($this->getQuickFormType($this->getSettingMetadata($setting)) === 'CheckBoxes') {
$settings[$setting] = array_keys($settingValue);
}
+ if ($this->getQuickFormType($this->getSettingMetadata($setting)) === 'CheckBox') {
+ // This will be an array with one value.
+ $settings[$setting] = (int) reset($settings[$setting]);
+ }
}
civicrm_api3('setting', 'create', $settings);
}
*/
class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
+ /**
+ * Return unique paths for checking for examples.
+ * @return array
+ */
+ private static function uniquePaths() {
+ // Ensure that paths with trailing slashes are properly dealt with
+ $paths = explode(PATH_SEPARATOR, get_include_path());
+ foreach ($paths as $id => $rawPath) {
+ $pathParts = explode(DIRECTORY_SEPARATOR, $rawPath);
+ foreach ($pathParts as $partId => $part) {
+ if (empty($part)) {
+ unset($pathParts[$partId]);
+ }
+ }
+ $newRawPath = implode(DIRECTORY_SEPARATOR, $pathParts);
+ if ($newRawPath != $rawPath) {
+ $paths[$id] = DIRECTORY_SEPARATOR . $newRawPath;
+ }
+ }
+ $paths = array_unique($paths);
+ return $paths;
+ }
+
+
/**
* Run page.
*
$this->assign('operators', CRM_Core_DAO::acceptedSQLOperators());
// List example directories
+ // use get_include_path to ensure that extensions are captured.
$examples = array();
- foreach (scandir(\Civi::paths()->getPath('[civicrm.root]/api/v3/examples')) as $item) {
- if ($item && strpos($item, '.') === FALSE) {
- $examples[] = $item;
+ $paths = self::uniquePaths();
+ foreach ($paths as $path) {
+ $dir = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples';
+ if (is_dir($dir)) {
+ foreach (scandir($dir) as $item) {
+ if ($item && strpos($item, '.') === FALSE && array_search($item, $examples) === FALSE) {
+ $examples[] = $item;
+ }
+ }
}
}
+ sort($examples);
$this->assign('examples', $examples);
return parent::run();
public static function getExampleFile() {
if (!empty($_GET['entity']) && strpos($_GET['entity'], '.') === FALSE) {
$examples = array();
- foreach (scandir(\Civi::paths()->getPath("[civicrm.root]/api/v3/examples/{$_GET['entity']}")) as $item) {
- $item = str_replace('.php', '', $item);
- if ($item && strpos($item, '.') === FALSE) {
- $examples[] = array('key' => $item, 'value' => $item);
+ $paths = self::uniquePaths();
+ foreach ($paths as $path) {
+ $dir = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $_GET['entity'];
+ if (is_dir($dir)) {
+ foreach (scandir($dir) as $item) {
+ $item = str_replace('.php', '', $item);
+ if ($item && strpos($item, '.') === FALSE) {
+ $examples[] = array('key' => $item, 'value' => $item);
+ }
+ }
}
}
CRM_Utils_JSON::output($examples);
}
if (!empty($_GET['file']) && strpos($_GET['file'], '.') === FALSE) {
- $fileName = \Civi::paths()->getPath("[civicrm.root]/api/v3/examples/{$_GET['file']}.php");
- if (file_exists($fileName)) {
- echo file_get_contents($fileName);
+ $paths = self::uniquePaths();
+ $fileFound = FALSE;
+ foreach ($paths as $path) {
+ $fileName = \CRM_Utils_File::addTrailingSlash($path) . 'api' . DIRECTORY_SEPARATOR . 'v3' . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $_GET['file'] . '.php';
+ if (!$fileFound && file_exists($fileName)) {
+ $fileFound = TRUE;
+ echo file_get_contents($fileName);
+ }
}
- else {
+ if (!$fileFound) {
echo "Not found.";
}
CRM_Utils_System::civiExit();
//get the location name
list($tName, $fldName) = self::getLocationTableName($field['where'], $locType);
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $fieldName = "LOWER(`$tName`.$fldName)";
+ $fieldName = "`$tName`.$fldName";
// we set both _tables & whereTables because whereTables doesn't seem to do what the name implies it should
$this->_tables[$tName] = $this->_whereTables[$tName] = 1;
}
else {
if ($op != 'IN' && !is_numeric($value) && !is_array($value)) {
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $fieldName = "LOWER({$field['where']})";
+ $fieldName = "{$field['where']}";
}
else {
$fieldName = "{$field['where']}";
//By default, $sub elements should be joined together with OR statements (don't change this variable).
$subGlue = ' OR ';
- $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
-
$firstChar = substr($value, 0, 1);
$lastChar = substr($value, -1, 1);
$quotes = array("'", '"');
elseif ($op == 'LIKE' && strpos($value, ',') === FALSE) {
$value = str_replace(' ', '%', $value);
}
- $value = $strtolower(CRM_Core_DAO::escapeString(trim($value)));
+ $value = CRM_Core_DAO::escapeString(trim($value));
if (strlen($value)) {
$fieldsub = array();
$value = "'" . self::getWildCardedValue($wildcard, $op, $value) . "'";
if ($fieldName == 'sort_name') {
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $wc = self::caseImportant($op) ? "LOWER(contact_a.sort_name)" : "contact_a.sort_name";
+ $wc = "contact_a.sort_name";
}
else {
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $wc = self::caseImportant($op) ? "LOWER(contact_a.display_name)" : "contact_a.display_name";
+ $wc = "contact_a.display_name";
}
$fieldsub[] = " ( $wc $op $value )";
if ($config->includeNickNameInName) {
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $wc = self::caseImportant($op) ? "LOWER(contact_a.nick_name)" : "contact_a.nick_name";
+ $wc = "contact_a.nick_name";
$fieldsub[] = " ( $wc $op $value )";
}
if ($config->includeEmailInName) {
return;
}
- $n = strtolower(trim($value));
+ $n = trim($value);
if ($n) {
if (substr($n, 0, 1) == '"' &&
substr($n, -1, 1) == '"'
$value = "%{$value}%";
}
$op = 'LIKE';
- // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
$this->_where[$grouping][] = self::buildClause('civicrm_address.street_address', $op, $value, 'String');
$this->_qill[$grouping][] = ts('Street') . " $op '$n'";
}
$returnProperties[$householdRelationshipType][$key] = $value;
}
}
+ // @todo - don't use returnProperties above.
+ $processor->setHouseholdMergeReturnProperties($returnProperties[$householdRelationshipType]);
}
}
}
- list($relationQuery, $allRelContactArray) = self::buildRelatedContactArray($selectAll, $ids, $processor, $componentTable, $returnProperties);
+ self::buildRelatedContactArray($selectAll, $ids, $processor, $componentTable);
// make sure the groups stuff is included only if specifically specified
// by the fields param (CRM-1969), else we limit the contacts outputted to only
}
if ($processor->isRelationshipTypeKey($field)) {
- $relDAO = CRM_Utils_Array::value($iterationDAO->contact_id, $allRelContactArray[$field]);
- $relationQuery[$field]->convertToPseudoNames($relDAO);
- self::fetchRelationshipDetails($relDAO, $value, $field, $row);
+ foreach (array_keys($value) as $property) {
+ if ($property === 'location') {
+ // @todo just undo all this nasty location wrangling!
+ foreach ($value['location'] as $locationKey => $locationFields) {
+ foreach (array_keys($locationFields) as $locationField) {
+ $fieldKey = str_replace(' ', '_', $locationKey . '-' . $locationField);
+ $row[$field . '_' . $fieldKey] = $processor->getRelationshipValue($field, $iterationDAO->contact_id, $fieldKey);
+ }
+ }
+ }
+ else {
+ $row[$field . '_' . $property] = $processor->getRelationshipValue($field, $iterationDAO->contact_id, $property);
+ }
+ }
}
else {
$row[$field] = self::getTransformedFieldValue($field, $iterationDAO, $fieldValue, $i18n, $metadata, $paymentDetails, $processor);
*/
public static function mergeSameHousehold($exportTempTable, &$sqlColumns, $prefix) {
$prefixColumn = $prefix . '_';
- $allKeys = array_keys($sqlColumns);
$replaced = array();
// name map of the non standard fields in header rows & sql columns
$mappingFields = array(
'civicrm_primary_id' => 'id',
- 'contact_source' => 'source',
- 'current_employer_id' => 'employer_id',
- 'contact_is_deleted' => 'is_deleted',
- 'name' => 'address_name',
'provider_id' => 'im_service_provider',
'phone_type_id' => 'phone_type',
);
$headerName = $field . '-' . 'current_employer';
}
else {
- $headerName = $field . '-' . $queryFields[$relationField]['name'];
+ $headerName = $field . '-' . $relationField;
}
}
$phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
$imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
$i18n = CRM_Core_I18n::singleton();
+ $field = $field . '_';
+
foreach ($value as $relationField => $relationValue) {
if (is_object($relDAO) && property_exists($relDAO, $relationField)) {
$fieldValue = $relDAO->$relationField;
else {
$fieldValue = '';
}
- $field = $field . '_';
$relPrefix = $field . $relationField;
if (is_object($relDAO) && $relationField == 'id') {
* @param $ids
* @param \CRM_Export_BAO_ExportProcessor $processor
* @param $componentTable
- * @param $returnProperties
- *
- * @return array
*/
- protected static function buildRelatedContactArray($selectAll, $ids, $processor, $componentTable, $returnProperties) {
+ protected static function buildRelatedContactArray($selectAll, $ids, $processor, $componentTable) {
$allRelContactArray = $relationQuery = array();
$queryMode = $processor->getQueryMode();
$exportMode = $processor->getExportMode();
- foreach (self::$relationshipTypes as $rel => $dnt) {
- if ($relationReturnProperties = CRM_Utils_Array::value($rel, $returnProperties)) {
- $allRelContactArray[$rel] = array();
- // build Query for each relationship
- $relationQuery[$rel] = new CRM_Contact_BAO_Query(NULL, $relationReturnProperties,
- NULL, FALSE, FALSE, $queryMode
- );
- list($relationSelect, $relationFrom, $relationWhere, $relationHaving) = $relationQuery[$rel]->query();
-
- list($id, $direction) = explode('_', $rel, 2);
- // identify the relationship direction
- $contactA = 'contact_id_a';
- $contactB = 'contact_id_b';
- if ($direction == 'b_a') {
- $contactA = 'contact_id_b';
- $contactB = 'contact_id_a';
- }
- $relIDs = self::getIDsForRelatedContact($ids, $exportMode);
- $relationshipJoin = $relationshipClause = '';
- if (!$selectAll && $componentTable) {
- $relationshipJoin = " INNER JOIN {$componentTable} ctTable ON ctTable.contact_id = {$contactA}";
- }
- elseif (!empty($relIDs)) {
- $relID = implode(',', $relIDs);
- $relationshipClause = " AND crel.{$contactA} IN ( {$relID} )";
- }
+ foreach ($processor->getRelationshipReturnProperties() as $relationshipKey => $relationReturnProperties) {
+ $allRelContactArray[$relationshipKey] = array();
+ // build Query for each relationship
+ $relationQuery = new CRM_Contact_BAO_Query(NULL, $relationReturnProperties,
+ NULL, FALSE, FALSE, $queryMode
+ );
+ list($relationSelect, $relationFrom, $relationWhere, $relationHaving) = $relationQuery->query();
+
+ list($id, $direction) = explode('_', $relationshipKey, 2);
+ // identify the relationship direction
+ $contactA = 'contact_id_a';
+ $contactB = 'contact_id_b';
+ if ($direction == 'b_a') {
+ $contactA = 'contact_id_b';
+ $contactB = 'contact_id_a';
+ }
+ $relIDs = self::getIDsForRelatedContact($ids, $exportMode);
+
+ $relationshipJoin = $relationshipClause = '';
+ if (!$selectAll && $componentTable) {
+ $relationshipJoin = " INNER JOIN {$componentTable} ctTable ON ctTable.contact_id = {$contactA}";
+ }
+ elseif (!empty($relIDs)) {
+ $relID = implode(',', $relIDs);
+ $relationshipClause = " AND crel.{$contactA} IN ( {$relID} )";
+ }
- $relationFrom = " {$relationFrom}
- INNER JOIN civicrm_relationship crel ON crel.{$contactB} = contact_a.id AND crel.relationship_type_id = {$id}
- {$relationshipJoin} ";
-
- //check for active relationship status only
- $today = date('Ymd');
- $relationActive = " AND (crel.is_active = 1 AND ( crel.end_date is NULL OR crel.end_date >= {$today} ) )";
- $relationWhere = " WHERE contact_a.is_deleted = 0 {$relationshipClause} {$relationActive}";
- $relationGroupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($relationQuery[$rel]->_select, "crel.{$contactA}");
- $relationSelect = "{$relationSelect}, {$contactA} as refContact ";
- $relationQueryString = "$relationSelect $relationFrom $relationWhere $relationHaving $relationGroupBy";
-
- $allRelContactDAO = CRM_Core_DAO::executeQuery($relationQueryString);
- while ($allRelContactDAO->fetch()) {
- //FIX Me: Migrate this to table rather than array
- // build the array of all related contacts
- $allRelContactArray[$rel][$allRelContactDAO->refContact] = clone($allRelContactDAO);
+ $relationFrom = " {$relationFrom}
+ INNER JOIN civicrm_relationship crel ON crel.{$contactB} = contact_a.id AND crel.relationship_type_id = {$id}
+ {$relationshipJoin} ";
+
+ //check for active relationship status only
+ $today = date('Ymd');
+ $relationActive = " AND (crel.is_active = 1 AND ( crel.end_date is NULL OR crel.end_date >= {$today} ) )";
+ $relationWhere = " WHERE contact_a.is_deleted = 0 {$relationshipClause} {$relationActive}";
+ $relationGroupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($relationQuery->_select, "crel.{$contactA}");
+ $relationSelect = "{$relationSelect}, {$contactA} as refContact ";
+ $relationQueryString = "$relationSelect $relationFrom $relationWhere $relationHaving $relationGroupBy";
+
+ $allRelContactDAO = CRM_Core_DAO::executeQuery($relationQueryString);
+ while ($allRelContactDAO->fetch()) {
+ $relationQuery->convertToPseudoNames($allRelContactDAO);
+ $row = [];
+ // @todo pass processor to fetchRelationshipDetails and set fields directly within it.
+ self::fetchRelationshipDetails($allRelContactDAO, $relationReturnProperties, $relationshipKey, $row);
+ foreach (array_keys($relationReturnProperties) as $property) {
+ if ($property === 'location') {
+ // @todo - simplify location in self::fetchRelationshipDetails - remove handling here. Or just call
+ // $processor->setRelationshipValue from fetchRelationshipDetails
+ foreach ($relationReturnProperties['location'] as $locationName => $locationValues) {
+ foreach (array_keys($locationValues) as $locationValue) {
+ $key = str_replace(' ', '_', $locationName) . '-' . $locationValue;
+ $processor->setRelationshipValue($relationshipKey, $allRelContactDAO->refContact, $key, $row[$relationshipKey . '__' . $key]);
+ }
+ }
+ }
+ else {
+ $processor->setRelationshipValue($relationshipKey, $allRelContactDAO->refContact, $property, $row[$relationshipKey . '_' . $property]);
+ }
}
- $allRelContactDAO->free();
}
}
- return array($relationQuery, $allRelContactArray);
}
/**
*/
protected $relationshipReturnProperties = [];
+ /**
+ * Get return properties by relationship.
+ * @return array
+ */
+ public function getRelationshipReturnProperties() {
+ return $this->relationshipReturnProperties;
+ }
+
+ /**
+ * Export values for related contacts.
+ *
+ * @var array
+ */
+ protected $relatedContactValues = [];
+
/**
* @var array
*/
$this->requestedFields = $requestedFields;
}
-
/**
* @return array
*/
);
}
+ /**
+ * Set the value for a relationship type field.
+ *
+ * In this case we are building up an array of properties for a related contact.
+ *
+ * These may be used for direct exporting or for merge to household depending on the
+ * options selected.
+ *
+ * @param string $relationshipType
+ * @param int $contactID
+ * @param string $field
+ * @param string $value
+ */
+ public function setRelationshipValue($relationshipType, $contactID, $field, $value) {
+ $this->relatedContactValues[$relationshipType][$contactID][$field] = $value;
+ }
+
+ /**
+ * Get the value for a relationship type field.
+ *
+ * In this case we are building up an array of properties for a related contact.
+ *
+ * These may be used for direct exporting or for merge to household depending on the
+ * options selected.
+ *
+ * @param string $relationshipType
+ * @param int $contactID
+ * @param string $field
+ *
+ * @return string
+ */
+ public function getRelationshipValue($relationshipType, $contactID, $field) {
+ return isset($this->relatedContactValues[$relationshipType][$contactID][$field]) ? $this->relatedContactValues[$relationshipType][$contactID][$field] : '';
+ }
+
/**
* @return bool
*/
return $this->relationshipReturnProperties[$relationshipKey];
}
+ /**
+ * Add the main return properties to the household merge properties if needed for merging.
+ *
+ * If we are using household merge we need to add these to the relationship properties to
+ * be retrieved.
+ *
+ * @param $returnProperties
+ */
+ public function setHouseholdMergeReturnProperties($returnProperties) {
+ foreach ($this->getHouseholdRelationshipTypes() as $householdRelationshipType) {
+ $this->relationshipReturnProperties[$householdRelationshipType] = $returnProperties;
+ }
+ }
+
/**
* Get the default location fields to request.
*
public static function whereClauseSingle(&$values, &$query) {
list($name, $op, $value, $grouping, $wildcard) = $values;
- $fields = array();
- $fields = self::getFields();
-
switch ($name) {
case 'mailing_id':
$selectedMailings = array_flip($value);
return;
case 'mailing_name':
- $value = strtolower(addslashes($value));
+ $value = addslashes($value);
if ($wildcard) {
$value = "%$value%";
$op = 'LIKE';
}
- // LOWER in query below roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
- $query->_where[$grouping][] = "LOWER(civicrm_mailing.name) $op '$value'";
+ $query->_where[$grouping][] = "civicrm_mailing.name $op '$value'";
$query->_qill[$grouping][] = "Mailing Namename $op \"$value\"";
$query->_tables['civicrm_mailing'] = $query->_whereTables['civicrm_mailing'] = 1;
$query->_tables['civicrm_mailing_recipients'] = $query->_whereTables['civicrm_mailing_recipients'] = 1;
$query['casContactIdField'] = 'e.contact_id';
$query['casEntityIdField'] = 'e.id';
$query['casContactTableAlias'] = NULL;
+
+ // Leaving this in case of legacy databases
$query['casDateField'] = str_replace('membership_', 'e.', $schedule->start_action_date);
+ // Options currently are just 'join_date', 'start_date', and 'end_date':
+ // they need an alias
+ if (strpos($query['casDateField'], 'e.') !== 0) {
+ $query['casDateField'] = 'e.' . $query['casDateField'];
+ }
+
// FIXME: Numbers should be constants.
if (in_array(2, $selectedStatuses)) {
//auto-renew memberships
->param('memberTypeValues', $selectedValues);
}
else {
+ // FIXME: The membership type is never null, so nobody will ever get a
+ // reminder if no membership types are selected. Either this should be a
+ // validation on the reminder form or all types should get a reminder if
+ // no types are selected.
$query->where("e.membership_type_id IS NULL");
}
+ // FIXME: This makes a lot of sense for renewal reminders, but a user
+ // scheduling another kind of reminder might not expect members to be
+ // excluded if they have status overrides. Ideally there would be some kind
+ // of setting per reminder.
$query->where("( e.is_override IS NULL OR e.is_override = 0 )");
+
+ // FIXME: Similarly to overrides, excluding contacts who can't edit the
+ // primary member makes sense in the context of renewals (see CRM-11342) but
+ // would be a surprise for other use cases.
$query->merge($this->prepareMembershipPermissionsFilter());
+
+ // FIXME: A lot of undocumented stuff happens with regard to
+ // `is_current_member`, and this is no exception. Ideally there would be an
+ // opportunity to pick statuses when setting up the scheduled reminder
+ // rather than making the assumptions here.
$query->where("e.status_id IN (#memberStatus)")
->param('memberStatus', \CRM_Member_PseudoConstant::membershipStatus(NULL, "(is_current_member = 1 OR name = 'Expired')", 'id'));
}
/**
- * @return array
+ * Filter out the memberships that are inherited from a contact that the
+ * recipient cannot edit.
+ *
+ * @return CRM_Utils_SQL_Select
*/
protected function prepareMembershipPermissionsFilter() {
- $query = '
-SELECT cm.id AS owner_id, cm.contact_id AS owner_contact, m.id AS slave_id, m.contact_id AS slave_contact, cmt.relationship_type_id AS relation_type, rel.contact_id_a, rel.contact_id_b, rel.is_permission_a_b, rel.is_permission_b_a
-FROM civicrm_membership m
-LEFT JOIN civicrm_membership cm ON cm.id = m.owner_membership_id
-LEFT JOIN civicrm_membership_type cmt ON cmt.id = m.membership_type_id
-LEFT JOIN civicrm_relationship rel ON ( ( rel.contact_id_a = m.contact_id AND rel.contact_id_b = cm.contact_id AND rel.relationship_type_id = cmt.relationship_type_id )
- OR ( rel.contact_id_a = cm.contact_id AND rel.contact_id_b = m.contact_id AND rel.relationship_type_id = cmt.relationship_type_id ) )
-WHERE m.owner_membership_id IS NOT NULL AND
- ( rel.is_permission_a_b = 0 OR rel.is_permission_b_a = 0)
-
-';
- $excludeIds = array();
- $dao = \CRM_Core_DAO::executeQuery($query, array());
- while ($dao->fetch()) {
- if ($dao->slave_contact == $dao->contact_id_a && $dao->is_permission_a_b == 0) {
- $excludeIds[] = $dao->slave_contact;
- }
- elseif ($dao->slave_contact == $dao->contact_id_b && $dao->is_permission_b_a == 0) {
- $excludeIds[] = $dao->slave_contact;
- }
- }
-
- if (!empty($excludeIds)) {
- return \CRM_Utils_SQL_Select::fragment()
- ->where("!casContactIdField NOT IN (#excludeMemberIds)")
- ->param(array(
- '#excludeMemberIds' => $excludeIds,
- ));
- }
- return NULL;
+ $joins = [
+ 'cm' => 'LEFT JOIN civicrm_membership cm ON cm.id = e.owner_membership_id',
+ 'rela' => 'LEFT JOIN civicrm_relationship rela ON rela.contact_id_a = e.contact_id AND rela.contact_id_b = cm.contact_id AND rela.is_permission_a_b = #editPerm',
+ 'relb' => 'LEFT JOIN civicrm_relationship relb ON relb.contact_id_a = cm.contact_id AND relb.contact_id_b = e.contact_id AND relb.is_permission_b_a = #editPerm',
+ ];
+
+ return \CRM_Utils_SQL_Select::fragment()
+ ->join(NULL, $joins)
+ ->param('#editPerm', CRM_Contact_BAO_Relationship::EDIT)
+ ->where('!( e.owner_membership_id IS NOT NULL AND rela.id IS NULL and relb.id IS NULL )');
}
}
AND {$this->_aliases['civicrm_batch']}.entity_table = 'civicrm_financial_trxn')";
}
- // for credit card type
- if ($this->isTableSelected('civicrm_financial_trxn')) {
- $this->_from .= "
- LEFT JOIN civicrm_entity_financial_trxn eftcc
- ON ({$this->_aliases['civicrm_contribution']}.id = eftcc.entity_id AND
- eftcc.entity_table = 'civicrm_contribution')
- LEFT JOIN civicrm_financial_trxn {$this->_aliases['civicrm_financial_trxn']}
- ON {$this->_aliases['civicrm_financial_trxn']}.id = eftcc.financial_trxn_id";
- }
+ $this->addFinancialTrxnFromClause();
}
/**
$addlCheck = \CRM_Utils_SQL_Select::from($query['casAddlCheckFrom'])
->select('*')
- ->merge($query, array('params', 'wheres'))// why only where? why not the joins?
+ ->merge($query, array('params', 'wheres', 'joins'))
->merge($this->prepareRepetitionEndFilter($query['casDateField']))
->limit(1)
->strict()
* @throws \CRM_Core_Exception
*/
public static function fireCaseChange(\Civi\Core\Event\PostEvent $event) {
- $caseId = NULL;
+ // Activities can be linked to multiple cases, so $caseIds might be an array or an int
+ $caseIds = NULL;
switch ($event->entity) {
case 'Activity':
if (!empty($event->object->case_id)) {
- $caseId = $event->object->case_id;
+ $caseIds = $event->object->case_id;
}
break;
// by the time we get the post-delete event, the record is gone, so
// there's nothing to analyze
if ($event->action != 'delete') {
- $caseId = $event->id;
+ $caseIds = $event->id;
}
break;
throw new \CRM_Core_Exception("CRM_Case_Listener does not support entity {$event->entity}");
}
- if ($caseId) {
- if (!isset(self::$isActive[$caseId])) {
- $tx = new \CRM_Core_Transaction();
- \CRM_Core_Transaction::addCallback(
- \CRM_Core_Transaction::PHASE_POST_COMMIT,
- array(__CLASS__, 'fireCaseChangeForRealz'),
- array($caseId),
- "Civi_CCase_Events::fire::{$caseId}"
- );
+ if ($caseIds) {
+ foreach ((array) $caseIds as $caseId) {
+ if (!isset(self::$isActive[$caseId])) {
+ $tx = new \CRM_Core_Transaction();
+ \CRM_Core_Transaction::addCallback(
+ \CRM_Core_Transaction::PHASE_POST_COMMIT,
+ array(__CLASS__, 'fireCaseChangeForRealz'),
+ array($caseId),
+ "Civi_CCase_Events::fire::{$caseId}"
+ );
+ }
}
}
}
'group_name' => 'Contribute Preferences',
'group' => 'contribute',
'name' => 'invoicing',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'quick_form_type' => 'Element',
'default' => 0,
'group_name' => 'Contribute Preferences',
'group' => 'contribute',
'name' => 'acl_financial_type',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'quick_form_type' => 'Element',
'default' => 0,
'group_name' => 'Contribute Preferences',
'group' => 'contribute',
'name' => 'deferred_revenue_enabled',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'quick_form_type' => 'Element',
'default' => 0,
'group' => 'contribute',
'name' => 'default_invoice_page',
'type' => 'Integer',
- 'quick_form_type' => 'Element',
+ 'quick_form_type' => 'Select',
'default' => NULL,
'pseudoconstant' => array(
// @todo - handle table style pseudoconstants for settings & avoid deprecated function.
'group_name' => 'Contribute Preferences',
'group' => 'contribute',
'name' => 'always_post_to_accounts_receivable',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'quick_form_type' => 'Element',
'default' => 0,
'group_name' => 'Contribute Preferences',
'group' => 'contribute',
'name' => 'update_contribution_on_membership_type_change',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'quick_form_type' => 'Element',
'default' => 0,
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
- * $Id$
- *
*/
/**
'group' => 'core',
'name' => 'ajaxPopupsEnabled',
'type' => 'Boolean',
- 'quick_form_type' => 'YesNo',
+ 'html_type' => 'checkbox',
'default' => 1,
'add' => '4.5',
'title' => ts('Enable Popup Forms'),
'group_name' => 'CiviCRM Preferences',
'group' => 'core',
'name' => 'activity_assignee_notification',
- 'type' => 'String',
- 'html_type' => 'Text',
+ 'type' => 'Boolean',
+ 'html_type' => 'checkbox',
'default' => '1',
'add' => '4.1',
'title' => ts('Notify Activity Assignees'),
'group_name' => 'CiviCRM Preferences',
'group' => 'core',
'name' => 'activity_assignee_notification_ics',
- 'type' => 'String',
- 'html_type' => 'Text',
+ 'type' => 'Boolean',
+ 'html_type' => 'checkbox',
'default' => '0',
'add' => '4.3',
'title' => ts('Include ICal Invite to Activity Assignees'),
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'profile_double_optin',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => '1',
'add' => '4.1',
- 'title' => 'Enable Double Opt-in for Profile Group(s) field',
+ 'title' => ts('Enable Double Opt-in for Profile Group(s) field'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.',
+ 'description' => ts('When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.'),
'help_text' => NULL,
),
'track_civimail_replies' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'track_civimail_replies',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => '0',
'add' => '4.1',
- 'title' => 'Track replies using VERP in Reply-To header',
+ 'title' => ts('Track replies using VERP in Reply-To header'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'If checked, mailings will default to tracking replies using VERP-ed Reply-To. ',
+ 'description' => ts('If checked, mailings will default to tracking replies using VERP-ed Reply-To. '),
'help_text' => NULL,
'validate_callback' => 'CRM_Core_BAO_Setting::validateBoolSetting',
),
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'civimail_workflow',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => '0',
'add' => '4.1',
- 'title' => 'Use CiviMail Workflow',
+ 'title' => ts('Enable workflow support for CiviMail'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.',
+ 'description' => ts('Drupal-only. Rules module must be enabled (beta feature - use with caution).'),
'help_text' => NULL,
),
'civimail_server_wide_lock' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'civimail_server_wide_lock',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => '0',
'add' => '4.1',
- 'title' => 'Lock Mails Server-Wide for Mail Sending',
+ 'title' => ts('Enable global server wide lock for CiviMail'),
'is_domain' => 1,
'is_contact' => 0,
'description' => NULL,
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'profile_add_to_group_double_optin',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => '0',
'add' => '4.1',
- 'title' => 'Enable Double Opt-in for Profile Group(s) field',
+ 'title' => ts('Enable Double Opt-in for Profile Group(s) field'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.',
+ 'description' => ts('When CiviMail is enabled, users who "subscribe" to a group from a profile Group(s) checkbox will receive a confirmation email. They must respond (opt-in) before they are added to the group.'),
'help_text' => NULL,
),
'disable_mandatory_tokens_check' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'disable_mandatory_tokens_check',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => 0,
'add' => '4.4',
- 'title' => 'Disable check for mandatory tokens',
+ 'title' => ts('Disable check for mandatory tokens'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'Don\'t check for presence of mandatory tokens (domain address; unsubscribe/opt-out) before sending mailings. WARNING: Mandatory tokens are a safe-guard which facilitate compliance with the US CAN-SPAM Act. They should only be disabled if your organization adopts other mechanisms for compliance or if your organization is not subject to CAN-SPAM.',
+ 'description' => ts('Don\'t check for presence of mandatory tokens (domain address; unsubscribe/opt-out) before sending mailings. WARNING: Mandatory tokens are a safe-guard which facilitate compliance with the US CAN-SPAM Act. They should only be disabled if your organization adopts other mechanisms for compliance or if your organization is not subject to CAN-SPAM.'),
'help_text' => NULL,
),
'dedupe_email_default' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'dedupe_email_default',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => 1,
'add' => '4.5',
- 'title' => 'CiviMail dedupes e-mail addresses by default',
+ 'title' => ts('CiviMail dedupes e-mail addresses by default'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'Set the "dedupe e-mail" option when sending a new mailing to "true" by default.',
+ 'description' => ts('Set the "dedupe e-mail" option when sending a new mailing to "true" by default.'),
'help_text' => NULL,
),
'hash_mailing_url' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'hash_mailing_url',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => 0,
'add' => '4.5',
- 'title' => 'Hashed Mailing URL\'s',
+ 'title' => ts('Hashed Mailing URL\'s'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'If enabled, a randomized hash key will be used to reference the mailing URL in the mailing.viewUrl token, instead of the mailing ID',
+ 'description' => ts('If enabled, a randomized hash key will be used to reference the mailing URL in the mailing.viewUrl token, instead of the mailing ID'),
'help_text' => NULL,
),
'civimail_multiple_bulk_emails' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'civimail_multiple_bulk_emails',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => 0,
'add' => '4.5',
- 'title' => ' Multiple Bulk Emails',
+ 'title' => ts('Enable multiple bulk email address for a contact.'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'If enabled, CiviMail will deliver a copy of the email to each bulk email listed for the contact.',
+ 'description' => ts('CiviMail will deliver a copy of the email to each bulk email listed for the contact.'),
'help_text' => NULL,
),
'include_message_id' => array(
'group_name' => 'Mailing Preferences',
'group' => 'mailing',
'name' => 'include_message_id',
- 'type' => 'Integer',
+ 'type' => 'Boolean',
'html_type' => 'checkbox',
'default' => FALSE,
'add' => '4.5',
- 'title' => 'Enable CiviMail to generate Message-ID header',
+ 'title' => ts('Enable CiviMail to generate Message-ID header'),
'is_domain' => 1,
'is_contact' => 0,
'description' => '',
'group' => 'mailing',
'name' => 'write_activity_record',
'type' => 'Boolean',
- 'quick_form_type' => 'YesNo',
+ 'html_type' => 'checkbox',
+ 'quick_form_type' => 'CheckBox',
'default' => '1',
'add' => '4.7',
- 'title' => 'Enable CiviMail to create activities on delivery',
+ 'title' => ts('Enable CiviMail to create activities on delivery'),
'is_domain' => 1,
'is_contact' => 0,
'description' => NULL,
'group' => 'mailing',
'name' => 'auto_recipient_rebuild',
'type' => 'Boolean',
- 'quick_form_type' => 'YesNo',
+ 'html_type' => 'checkbox',
+ 'quick_form_type' => 'CheckBox',
'default' => '1',
- 'title' => 'Enable automatic CiviMail recipient count display',
+ 'title' => ts('Enable automatic CiviMail recipient count display'),
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'Enable this setting to rebuild recipient list automatically during composing mail. Disable will allow you to rebuild recipient manually.',
- 'help_text' => 'CiviMail automatically fetches recipient list and count whenever mailing groups are included or excluded while composing bulk mail. This phenomena may degrade performance for large sites, so disable this setting to build and fetch recipients for selected groups, manually.',
+ 'description' => ts('Enable this setting to rebuild recipient list automatically during composing mail. Disable will allow you to rebuild recipient manually.'),
+ 'help_text' => ts('CiviMail automatically fetches recipient list and count whenever mailing groups are included or excluded while composing bulk mail. This phenomena may degrade performance for large sites, so disable this setting to build and fetch recipients for selected groups, manually.'),
),
'allow_mail_from_logged_in_contact' => array(
'group_name' => 'Mailing Preferences',
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
- * $Id$
- *
*/
-/*
+
+/**
* Settings metadata file
*/
'group_name' => 'Multi Site Preferences',
'group' => 'multisite',
'name' => 'is_enabled',
- 'title' => 'Multisite Is enabled',
- 'type' => 'Integer',
+ 'title' => ts('Enable Multi Site Configuration'),
+ 'html_type' => 'checkbox',
+ 'type' => 'Boolean',
'default' => '0',
'add' => '4.1',
'is_domain' => 1,
'is_contact' => 0,
- 'description' => 'Multisite is enabled',
+ 'description' => ts('Make CiviCRM aware of multiple domains. You should configure a domain group if enabled'),
+ 'help_link' => ['page' => 'Multi Site Installation', 'resource' => 'wiki'],
'help_text' => NULL,
),
'domain_group_id' => array(
'group_name' => 'Multi Site Preferences',
'group' => 'multisite',
'name' => 'domain_group_id',
- 'title' => 'Multisite Domain Group',
+ 'title' => ts('Multisite Domain Group'),
'type' => 'Integer',
+ 'html_type' => 'entity_reference',
+ 'entity_reference_options' => ['entity' => 'group', 'select' => array('minimumInputLength' => 0)],
'default' => '0',
'add' => '4.1',
'is_domain' => 1,
'is_contact' => 0,
- 'description' => NULL,
+ 'description' => ts('Contacts created on this site are added to this group'),
'help_text' => NULL,
),
'event_price_set_domain_id' => array(
{if $field.html_type EQ 'checkbox'|| $field.html_type EQ 'checkboxes'}
<td class="label"></td>
<td>
- {$form.$n.html} {$form.$n.label}
+ {$form.$n.html}
{if $field.description}
<br /><span class="description">{$field.description}</span>
{/if}
0 => array(
0 => 'email',
1 => 'LIKE',
- 2 => 'secondary@example.com',
+ 2 => 'sEcondary@example.com',
3 => 0,
4 => 1,
),
CRM_Core_Config::singleton()->defaultSearchProfileID = 1;
$this->callAPISuccess('address', 'create', array(
'contact_id' => $contactID,
- 'city' => 'Cool City',
- 'street_address' => 'Long Street',
+ 'city' => 'Cool CITY',
+ 'street_address' => 'Long STREET',
'location_type_id' => 1,
));
$returnProperties = array(
public function getSearchProfileData() {
return [
[
- [['city', '=', 'Cool City', 1, 0]], "civicrm_address.city as `city`", "LOWER(civicrm_address.city) = 'cool city'",
+ [['city', '=', 'Cool City', 1, 0]], "civicrm_address.city as `city`", "civicrm_address.city = 'cool city'",
],
[
// Note that in the query 'long street' is lower cased. We eventually want to change that & not mess with the vars - it turns out
'start_action_unit' => 'week',
'subject' => 'subject sched_membership_join_2week (joined {membership.join_date})',
);
+ $this->fixtures['sched_membership_start_1week'] = array(
+ 'name' => 'sched_membership_start_1week',
+ 'title' => 'sched_membership_start_1week',
+ 'absolute_date' => '',
+ 'body_html' => '<p>body sched_membership_start_1week</p>',
+ 'body_text' => 'body sched_membership_start_1week',
+ 'end_action' => '',
+ 'end_date' => '',
+ 'end_frequency_interval' => '',
+ 'end_frequency_unit' => '',
+ 'entity_status' => '',
+ 'entity_value' => '',
+ 'group_id' => '',
+ 'is_active' => 1,
+ 'is_repeat' => '0',
+ 'mapping_id' => 4,
+ 'msg_template_id' => '',
+ 'recipient' => '',
+ 'recipient_listing' => '',
+ 'recipient_manual' => '',
+ 'record_activity' => 1,
+ 'repetition_frequency_interval' => '',
+ 'repetition_frequency_unit' => '',
+ 'start_action_condition' => 'after',
+ 'start_action_date' => 'membership_start_date',
+ 'start_action_offset' => '1',
+ 'start_action_unit' => 'week',
+ 'subject' => 'subject sched_membership_start_1week (joined {membership.start_date})',
+ );
$this->fixtures['sched_membership_end_2week'] = array(
'name' => 'sched_membership_end_2week',
'title' => 'sched_membership_end_2week',
* an email should be sent.
*/
public function testMembershipDateMatch() {
- foreach (['membership_join_date', 'membership_start_date'] as $date) {
- $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 1)));
- $this->assertTrue(is_numeric($membership->id));
- $result = $this->callAPISuccess('Email', 'create', array(
- 'contact_id' => $membership->contact_id,
- 'email' => 'test-member@example.com',
- 'location_type_id' => 1,
- ));
- $this->assertAPISuccess($result);
+ $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 1)));
+ $this->assertTrue(is_numeric($membership->id));
+ $result = $this->callAPISuccess('Email', 'create', array(
+ 'contact_id' => $membership->contact_id,
+ 'email' => 'test-member@example.com',
+ 'location_type_id' => 1,
+ 'is_primary' => 1,
+ ));
- $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
- $actionSchedule = $this->fixtures['sched_membership_join_2week'];
- $actionSchedule['start_action_date'] = $date;
- $actionSchedule['entity_value'] = $membership->membership_type_id;
- $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
- $this->assertTrue(is_numeric($actionScheduleDao->id));
+ $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
+ $actionSchedule = $this->fixtures['sched_membership_join_2week'];
+ $actionSchedule['entity_value'] = $membership->membership_type_id;
+ $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
+ $this->assertTrue(is_numeric($actionScheduleDao->id));
- // start_date=2012-03-15 ; schedule is 2 weeks after start_date
- $this->assertCronRuns(array(
- array(
- // Before the 2-week mark, no email.
- 'time' => '2012-03-28 01:00:00',
- 'recipients' => array(),
- 'subjects' => array(),
- ),
- array(
- // After the 2-week mark, send an email.
- 'time' => '2012-03-29 01:00:00',
- 'recipients' => array(array('test-member@example.com')),
- 'subjects' => array('subject sched_membership_join_2week (joined March 15th, 2012)'),
- ),
- ));
- }
+ // start_date=2012-03-15 ; schedule is 2 weeks after join_date
+ $this->assertCronRuns(array(
+ array(
+ // Before the 2-week mark, no email.
+ 'time' => '2012-03-28 01:00:00',
+ 'recipients' => array(),
+ 'subjects' => array(),
+ ),
+ array(
+ // After the 2-week mark, send an email.
+ 'time' => '2012-03-29 01:00:00',
+ 'recipients' => array(array('test-member@example.com')),
+ 'subjects' => array('subject sched_membership_join_2week (joined March 15th, 2012)'),
+ ),
+ ));
+
+ $actionSchedule = $this->fixtures['sched_membership_start_1week'];
+ $actionSchedule['entity_value'] = $membership->membership_type_id;
+ $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
+ $this->assertTrue(is_numeric($actionScheduleDao->id));
+
+ // start_date=2012-03-15 ; schedule is 1 weeks after start_date
+ $this->assertCronRuns(array(
+ array(
+ // Before the 2-week mark, no email.
+ 'time' => '2012-03-21 01:00:00',
+ 'recipients' => array(),
+ 'subjects' => array(),
+ ),
+ array(
+ // After the 2-week mark, send an email.
+ 'time' => '2012-03-22 01:00:00',
+ 'recipients' => array(array('test-member@example.com')),
+ 'subjects' => array('subject sched_membership_start_1week (joined March 15th, 2012)'),
+ ),
+ ));
}
}
}
+ /**
+ * Inherited members without permission to edit the main member contact should
+ * not get reminders.
+ *
+ * However, just because a contact inherits one membership doesn't mean
+ * reminders for other memberships should be suppressed.
+ *
+ * See CRM-14098
+ */
+ public function testInheritedMembershipPermissions() {
+ // Set up common parameters for memberships.
+ $membershipParams = $this->fixtures['rolling_membership'];
+ $membershipParams['status_id'] = 1;
+
+ $membershipParams['membership_type_id']['relationship_type_id'] = 1;
+ $membershipParams['membership_type_id']['relationship_direction'] = 'b_a';
+ $membershipType1 = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipParams['membership_type_id']);
+
+ // We'll create a new membership type that can be held at the same time as
+ // the first one.
+ $membershipParams['membership_type_id']['relationship_type_id'] = 'NULL';
+ $membershipParams['membership_type_id']['relationship_direction'] = 'NULL';
+ $membershipType2 = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipParams['membership_type_id']);
+
+ // Create the parent membership and contact
+ $membershipParams['membership_type_id'] = $membershipType1->id;
+ $mainMembership = $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
+
+ $contactParams = [
+ 'contact_type' => 'Individual',
+ 'first_name' => 'Mom',
+ 'last_name' => 'Rel',
+ 'is_deceased' => 0,
+ ];
+ $this->createTestObject('CRM_Contact_DAO_Contact', array_merge($contactParams, ['id' => $mainMembership->contact_id]));
+
+ $emailParams = [
+ 'contact_id' => $mainMembership->contact_id,
+ 'email' => 'test-member@example.com',
+ 'location_type_id' => 1,
+ 'is_primary' => 1,
+ ];
+ $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
+
+ // Set up contacts and emails for the two children
+ $contactParams['first_name'] = 'Favorite';
+ $permChild = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
+ $emailParams['email'] = 'favorite@example.com';
+ $emailParams['contact_id'] = $permChild->id;
+ $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
+
+ $contactParams['first_name'] = 'Black Sheep';
+ $nonPermChild = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
+ $emailParams['email'] = 'black.sheep@example.com';
+ $emailParams['contact_id'] = $nonPermChild->id;
+ $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
+
+ // Each child gets a relationship, one with permission to edit the parent. This
+ // will trigger inherited memberships for the first membership type
+ $relParams = [
+ 'relationship_type_id' => 1,
+ 'contact_id_a' => $nonPermChild->id,
+ 'contact_id_b' => $mainMembership->contact_id,
+ 'is_active' => 1,
+ ];
+ $this->callAPISuccess('relationship', 'create', $relParams);
+
+ $relParams['contact_id_a'] = $permChild->id;
+ $relParams['is_permission_a_b'] = CRM_Contact_BAO_Relationship::EDIT;
+ $this->callAPISuccess('relationship', 'create', $relParams);
+
+ // Mom and Black Sheep get their own memberships of the second type.
+ $membershipParams['membership_type_id'] = $membershipType2->id;
+ $membershipParams['owner_membership_id'] = 'NULL';
+ $membershipParams['contact_id'] = $mainMembership->contact_id;
+ $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
+
+ $membershipParams['contact_id'] = $nonPermChild->id;
+ $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
+
+ // Test a reminder for the first membership type - that should exclude Black
+ // Sheep.
+ $actionSchedule = $this->fixtures['sched_membership_join_2week'];
+ $actionSchedule['entity_value'] = $membershipType1->id;
+ $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
+ $this->assertTrue(is_numeric($actionScheduleDao->id));
+
+ $this->assertCronRuns([
+ [
+ 'time' => '2012-03-29 01:00:00',
+ 'recipients' => [['test-member@example.com'], ['favorite@example.com']],
+ 'subjects' => [
+ 'subject sched_membership_join_2week (joined March 15th, 2012)',
+ 'subject sched_membership_join_2week (joined March 15th, 2012)',
+ ],
+ ],
+ ]);
+
+ // Test a reminder for the second membership type - that should include
+ // Black Sheep.
+ $actionSchedule = $this->fixtures['sched_membership_start_1week'];
+ $actionSchedule['entity_value'] = $membershipType2->id;
+ $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
+ $this->assertTrue(is_numeric($actionScheduleDao->id));
+
+ $this->assertCronRuns([
+ [
+ 'time' => '2012-03-22 01:00:00',
+ 'recipients' => [['test-member@example.com'], ['black.sheep@example.com']],
+ 'subjects' => [
+ 'subject sched_membership_start_1week (joined March 15th, 2012)',
+ 'subject sched_membership_start_1week (joined March 15th, 2012)',
+ ],
+ ],
+ ]);
+ }
+
public function createModifiedDateTime($origDateTime, $modifyRule) {
$newDateTime = clone($origDateTime);
$newDateTime->modify($modifyRule);
$this->assertEquals('Big campaign,', CRM_Core_DAO::singleValueQuery("SELECT GROUP_CONCAT(contribution_campaign_title) FROM {$tableName}"));
}
+ /**
+ * Test exporting relationships.
+ */
+ public function testExportRelationships() {
+ $organization1 = $this->organizationCreate(['organization_name' => 'Org 1', 'legal_name' => 'pretty legal', 'contact_source' => 'friend who took a law paper once']);
+ $organization2 = $this->organizationCreate(['organization_name' => 'Org 2', 'legal_name' => 'well dodgey']);
+ $contact1 = $this->individualCreate(['employer_id' => $organization1, 'first_name' => 'one']);
+ $contact2 = $this->individualCreate(['employer_id' => $organization2, 'first_name' => 'one']);
+ $employerRelationshipTypeID = $this->callAPISuccessGetValue('RelationshipType', ['return' => 'id', 'label_a_b' => 'Employee of']);
+ $selectedFields = [
+ ['Individual', 'first_name', ''],
+ ['Individual', $employerRelationshipTypeID . '_a_b', 'organization_name', ''],
+ ['Individual', $employerRelationshipTypeID . '_a_b', 'legal_name', ''],
+ ['Individual', $employerRelationshipTypeID . '_a_b', 'contact_source', ''],
+ ];
+ list($tableName, $sqlColumns, $headerRows) = CRM_Export_BAO_Export::exportComponents(
+ FALSE,
+ [$contact1, $contact2],
+ [],
+ NULL,
+ $selectedFields,
+ NULL,
+ CRM_Export_Form_Select::CONTACT_EXPORT,
+ "contact_a.id IN ( $contact1, $contact2 )",
+ NULL,
+ FALSE,
+ FALSE,
+ [
+ 'exportOption' => CRM_Export_Form_Select::CONTACT_EXPORT,
+ 'suppress_csv_for_testing' => TRUE,
+ ]
+ );
+
+ $dao = CRM_Core_DAO::executeQuery("SELECT * FROM {$tableName}");
+ $dao->fetch();
+ $this->assertEquals('one', $dao->first_name);
+ $this->assertEquals('Org 1', $dao->{$employerRelationshipTypeID . '_a_b_organization_name'});
+ $this->assertEquals('pretty legal', $dao->{$employerRelationshipTypeID . '_a_b_legal_name'});
+ $this->assertEquals('friend who took a law paper once', $dao->{$employerRelationshipTypeID . '_a_b_contact_source'});
+
+ $dao->fetch();
+ $this->assertEquals('Org 2', $dao->{$employerRelationshipTypeID . '_a_b_organization_name'});
+ $this->assertEquals('well dodgey', $dao->{$employerRelationshipTypeID . '_a_b_legal_name'});
+ }
+
/**
* Test exporting relationships.
*
['Individual', $houseHoldTypeID . '_a_b', 'city', ''],
['Individual', 'city', ''],
['Individual', 'state_province', ''],
+ ['Individual', 'contact_source', ''],
];
list($tableName, $sqlColumns, $headerRows) = CRM_Export_BAO_Export::exportComponents(
FALSE,
$this->assertEquals('ME', $dao->state_province);
$this->assertEquals($householdID, $dao->civicrm_primary_id);
$this->assertEquals($householdID, $dao->civicrm_primary_id);
+ $this->assertEquals('household sauce', $dao->contact_source);
}
$this->assertEquals([
0 => 'City',
1 => 'State',
- 2 => 'Household ID',
+ 2 => 'Contact Source',
+ 3 => 'Household ID',
], $headerRows);
$this->assertEquals(
[
'city' => 'city varchar(64)',
'state_province' => 'state_province varchar(64)',
'civicrm_primary_id' => 'civicrm_primary_id varchar(16)',
+ 'contact_source' => 'contact_source varchar(255)',
], $sqlColumns);
}
protected function setUpHousehold() {
$this->setUpContactExportData();
$householdID = $this->householdCreate([
+ 'source' => 'household sauce',
'api.Address.create' => [
'city' => 'Portland',
'state_province_id' => 'Maine',
$this->getAndCheck($params, $contact['id'], 'contact');
}
+ /**
+ * Test that name searches are case insensitive.
+ */
+ public function testGetNameVariantsCaseInsensitive() {
+ $this->callAPISuccess('contact', 'create', [
+ 'display_name' => 'Abc1',
+ 'contact_type' => 'Individual',
+ ]);
+ $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
+ $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
+ Civi::settings()->set('includeNickNameInName', TRUE);
+ $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
+ $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
+ Civi::settings()->set('includeNickNameInName', FALSE);
+ }
+
/**
* Test old keys still work.
*
* CRM-15443 - ensure getlist api does not return deleted contacts.
*/
public function testGetlistExcludeConditions() {
- $name = md5(time());
+ $name = 'Scarabée';
$contact = $this->individualCreate(array('last_name' => $name));
$this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
$this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));