diff --git a/CRM/ACL/Page/EntityRole.php b/CRM/ACL/Page/EntityRole.php index 7a1b510a6ec2..4fbd6215cda1 100644 --- a/CRM/ACL/Page/EntityRole.php +++ b/CRM/ACL/Page/EntityRole.php @@ -121,6 +121,7 @@ public function run() { // finally browse the acl's if ($this->_action & CRM_Core_Action::BROWSE) { + $this->browse(); } // This replaces parent run, but do parent's parent run diff --git a/CRM/Admin/Form/MessageTemplates.php b/CRM/Admin/Form/MessageTemplates.php index c7ef91f53002..7e2330dc5137 100644 --- a/CRM/Admin/Form/MessageTemplates.php +++ b/CRM/Admin/Form/MessageTemplates.php @@ -69,49 +69,17 @@ public function setDefaultValues() { $defaults['file_type'] = 0; } - $this->_workflow_id = CRM_Utils_Array::value('workflow_id', $defaults); - $this->assign('workflow_id', $this->_workflow_id); if ($this->_action & CRM_Core_Action::ADD) { $defaults['is_active'] = 1; - //set the context for redirection after form submit or cancel - $session = CRM_Core_Session::singleton(); - $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/messageTemplates', - 'selectedChild=user&reset=1' - )); } - // FIXME: we need to fix the Cancel button here as we don’t know whether it’s a workflow template in buildQuickForm() if ($this->_action & CRM_Core_Action::UPDATE) { - if ($this->_workflow_id) { - $selectedChild = 'workflow'; - } - else { - $selectedChild = 'user'; - } - $documentInfo = CRM_Core_BAO_File::getEntityFile('civicrm_msg_template', $this->_id, TRUE); if (!empty($documentInfo)) { $defaults['file_type'] = 1; $this->_is_document = TRUE; $this->assign('attachment', $documentInfo); } - - $cancelURL = CRM_Utils_System::url('civicrm/admin/messageTemplates', "selectedChild={$selectedChild}&reset=1"); - $cancelURL = str_replace('&', '&', $cancelURL); - $this->addButtons( - array( - array( - 'type' => 'upload', - 'name' => ts('Save'), - 'isDefault' => TRUE, - ), - array( - 'type' => 'cancel', - 'name' => ts('Cancel'), - 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"), - ), - ) - ); } return $defaults; @@ -121,7 +89,6 @@ public function setDefaultValues() { * Build the form object. */ public function buildQuickForm() { - // For VIEW we only want Done button if ($this->_action & CRM_Core_Action::VIEW) { // currently, the above action is used solely for previewing default workflow templates @@ -138,18 +105,36 @@ public function buildQuickForm() { ); } else { - $this->addButtons(array( - array( - 'type' => 'upload', - 'name' => $this->_action & CRM_Core_Action::DELETE ? ts('Delete') : ts('Save'), - 'isDefault' => TRUE, - ), - array( - 'type' => 'cancel', - 'name' => ts('Cancel'), - ), - ) + $this->_workflow_id = CRM_Utils_Array::value('workflow_id', $this->_values); + $this->assign('workflow_id', $this->_workflow_id); + + if ($this->_workflow_id) { + $selectedChild = 'workflow'; + } + else { + $selectedChild = 'user'; + } + + $cancelURL = CRM_Utils_System::url('civicrm/admin/messageTemplates', "selectedChild={$selectedChild}&reset=1"); + $cancelURL = str_replace('&', '&', $cancelURL); + $buttons[] = array( + 'type' => 'upload', + 'name' => $this->_action & CRM_Core_Action::DELETE ? ts('Delete') : ts('Save'), + 'isDefault' => TRUE, ); + if (!($this->_action & CRM_Core_Action::DELETE)) { + $buttons[] = array( + 'type' => 'submit', + 'name' => ts('Save and Done'), + 'subName' => 'done', + ); + } + $buttons[] = array( + 'type' => 'cancel', + 'name' => ts('Cancel'), + 'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"), + ); + $this->addButtons($buttons); } if ($this->_action & CRM_Core_Action::DELETE) { @@ -221,7 +206,6 @@ public function buildQuickForm() { ); $this->add('checkbox', 'is_active', ts('Enabled?')); - $this->addFormRule(array(__CLASS__, 'formRule'), $this); if ($this->_action & CRM_Core_Action::VIEW) { @@ -243,13 +227,11 @@ public function buildQuickForm() { * array of errors */ public static function formRule($params, $files, $self) { - $errors = array(); - // If user uploads non-document file other than odt/docx if (!empty($files['file_id']['tmp_name']) && array_search($files['file_id']['type'], CRM_Core_SelectValues::documentApplicationType()) == NULL ) { - $error['file_id'] = ts('Invalid document file format'); + $errors['file_id'] = ts('Invalid document file format'); } // If default is not set and no document file is uploaded elseif (empty($files['file_id']['tmp_name']) && !empty($params['file_type']) && !$self->_is_document) { @@ -257,7 +239,7 @@ public static function formRule($params, $files, $self) { $errors['file_id'] = ts('Please upload document'); } - return $errors; + return empty($errors) ? TRUE : $errors; } /** @@ -272,10 +254,8 @@ public function postProcess() { CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/messageTemplates', 'selectedChild=workflow&reset=1')); } else { - $params = array(); - // store the submitted values in an array - $params = $this->controller->exportValues($this->_name); + $params = $this->controller->exportValues(); if ($this->_action & CRM_Core_Action::UPDATE) { $params['id'] = $this->_id; @@ -286,7 +266,7 @@ public function postProcess() { unset($params['msg_text']); CRM_Utils_File::formatFile($params, 'file_id'); } - // delete related file refernces if html/text/pdf template are chosen over document + // delete related file references if html/text/pdf template are chosen over document elseif (!empty($this->_id)) { $entityFileDAO = new CRM_Core_DAO_EntityFile(); $entityFileDAO->entity_id = $this->_id; @@ -300,6 +280,7 @@ public function postProcess() { } } + $this->_workflow_id = CRM_Utils_Array::value('workflow_id', $this->_values); if ($this->_workflow_id) { $params['workflow_id'] = $this->_workflow_id; $params['is_active'] = TRUE; @@ -308,12 +289,15 @@ public function postProcess() { $messageTemplate = CRM_Core_BAO_MessageTemplate::add($params); CRM_Core_Session::setStatus(ts('The Message Template \'%1\' has been saved.', array(1 => $messageTemplate->msg_title)), ts('Saved'), 'success'); + if (isset($this->_submitValues['_qf_MessageTemplates_upload'])) { + // Save button was pressed + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/messageTemplates/add', "action=update&id={$messageTemplate->id}&reset=1")); + } + // Save and done button was pressed if ($this->_workflow_id) { CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/messageTemplates', 'selectedChild=workflow&reset=1')); } - else { - CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/messageTemplates', 'selectedChild=user&reset=1')); - } + CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/messageTemplates', 'selectedChild=user&reset=1')); } } diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index eb58c2ecc022..69dbcf0fa4e6 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -2761,6 +2761,10 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima $from .= CRM_Mailing_BAO_Query::from($name, $mode, $side); continue; } + elseif ($mode & CRM_Contact_BAO_Query::MODE_CAMPAIGN) { + $from .= CRM_Campaign_BAO_Query::from($name, $mode, $side); + continue; + } case 'civicrm_website': $from .= " $side JOIN civicrm_website ON contact_a.id = civicrm_website.contact_id "; diff --git a/CRM/Contact/DAO/Contact.php b/CRM/Contact/DAO/Contact.php index 02a08b2caf3c..98a2c243e5b5 100644 --- a/CRM/Contact/DAO/Contact.php +++ b/CRM/Contact/DAO/Contact.php @@ -30,7 +30,7 @@ * * Generated from xml/schema/CRM/Contact/Contact.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:6b04aae8fb2f9ebedb5aa9c792b81e30) + * (GenCodeChecksum:1e87927c8c8bdec9acfe3c306bb711d4) */ require_once 'CRM/Core/DAO.php'; require_once 'CRM/Utils/Type.php'; @@ -968,6 +968,10 @@ static function &fields() { 'entity' => 'Contact', 'bao' => 'CRM_Contact_BAO_Contact', 'localizable' => 0, + 'pseudoconstant' => array( + 'optionGroupName' => 'email_greeting', + 'optionEditPath' => 'civicrm/admin/options/email_greeting', + ) ) , 'email_greeting_custom' => array( 'name' => 'email_greeting_custom', @@ -1016,6 +1020,10 @@ static function &fields() { 'html' => array( 'type' => 'Text', ) , + 'pseudoconstant' => array( + 'optionGroupName' => 'postal_greeting', + 'optionEditPath' => 'civicrm/admin/options/postal_greeting', + ) ) , 'postal_greeting_custom' => array( 'name' => 'postal_greeting_custom', @@ -1081,6 +1089,10 @@ static function &fields() { 'html' => array( 'type' => 'Text', ) , + 'pseudoconstant' => array( + 'optionGroupName' => 'addressee', + 'optionEditPath' => 'civicrm/admin/options/addressee', + ) ) , 'addressee_display' => array( 'name' => 'addressee_display', diff --git a/CRM/Contact/Form/Edit/CommunicationPreferences.php b/CRM/Contact/Form/Edit/CommunicationPreferences.php index 2dae66963669..20f08e501bb6 100644 --- a/CRM/Contact/Form/Edit/CommunicationPreferences.php +++ b/CRM/Contact/Form/Edit/CommunicationPreferences.php @@ -131,7 +131,7 @@ public static function formRule($fields, $files, $self) { $greetings = self::getGreetingFields($self->_contactType); foreach ($greetings as $greeting => $details) { - $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name'); + $customizedValue = CRM_Core_PseudoConstant::getKey('CRM_Contact_BAO_Contact', $details['field'], 'Customized'); if (CRM_Utils_Array::value($details['field'], $fields) == $customizedValue && empty($fields[$details['customField']])) { $errors[$details['customField']] = ts('Custom %1 is a required field if %1 is of type Customized.', array(1 => $details['label']) diff --git a/CRM/Contact/Form/Task/Email.php b/CRM/Contact/Form/Task/Email.php index 42259eec6bb3..efc5ac5616b8 100644 --- a/CRM/Contact/Form/Task/Email.php +++ b/CRM/Contact/Form/Task/Email.php @@ -131,11 +131,7 @@ public function preProcess() { if (!$cid && $this->_context != 'standalone') { parent::preProcess(); } - - //early prevent, CRM-6209 - if (count($this->_contactIds) > CRM_Contact_Form_Task_EmailCommon::MAX_EMAILS_KILL_SWITCH) { - CRM_Core_Error::statusBounce(ts('Please do not use this task to send a lot of emails (greater than %1). We recommend using CiviMail instead.', array(1 => CRM_Contact_Form_Task_EmailCommon::MAX_EMAILS_KILL_SWITCH))); - } + CRM_Contact_Form_Task_EmailCommon::bounceIfSimpleMailLimitExceeded(count($this->_contactIds)); $this->assign('single', $this->_single); if (CRM_Core_Permission::check('administer CiviCRM')) { diff --git a/CRM/Contact/Form/Task/EmailCommon.php b/CRM/Contact/Form/Task/EmailCommon.php index 8757cac0d2bb..88be4a082bdf 100644 --- a/CRM/Contact/Form/Task/EmailCommon.php +++ b/CRM/Contact/Form/Task/EmailCommon.php @@ -409,11 +409,7 @@ public static function formRule($fields, $dontCare, $self) { * @param CRM_Core_Form $form */ public static function postProcess(&$form) { - if (count($form->_contactIds) > self::MAX_EMAILS_KILL_SWITCH) { - CRM_Core_Error::fatal(ts('Please do not use this task to send a lot of emails (greater than %1). We recommend using CiviMail instead.', - array(1 => self::MAX_EMAILS_KILL_SWITCH) - )); - } + self::bounceIfSimpleMailLimitExceeded(count($form->_contactIds)); // check and ensure that $formValues = $form->controller->exportValues($form->getName()); @@ -626,4 +622,19 @@ protected static function saveMessageTemplate($formValues) { } } + /** + * Bounce if there are more emails than permitted. + * + * @param int $count + * The number of emails the user is attempting to send + */ + public static function bounceIfSimpleMailLimitExceeded($count) { + $limit = Civi::settings()->get('simple_mail_limit'); + if ($count > $limit) { + CRM_Core_Error::statusBounce(ts('Please do not use this task to send a lot of emails (greater than %1). Many countries have legal requirements when sending bulk emails and the CiviMail framework has opt out functionality and domain tokens to help meet these.', + array(1 => $limit) + )); + } + } + } diff --git a/CRM/Contact/Task.php b/CRM/Contact/Task.php index 503c511e994d..d5afbac86de6 100644 --- a/CRM/Contact/Task.php +++ b/CRM/Contact/Task.php @@ -109,7 +109,7 @@ public static function initTasks() { 'result' => FALSE, ), self::EMAIL_CONTACTS => array( - 'title' => ts('Email - send now (to 50 or less)'), + 'title' => ts('Email - send now (to %1 or less)', array(1 => Civi::settings()->get('simple_mail_limit'))), 'class' => 'CRM_Contact_Form_Task_Email', 'result' => TRUE, 'url' => 'civicrm/task/send-email', diff --git a/CRM/Contribute/Form/Contribution/Confirm.php b/CRM/Contribute/Form/Contribution/Confirm.php index e5bfaf06bc0a..a2d95bdc9b1d 100644 --- a/CRM/Contribute/Form/Contribution/Confirm.php +++ b/CRM/Contribute/Form/Contribution/Confirm.php @@ -1443,7 +1443,7 @@ protected function postProcessMembership( $isTest = CRM_Utils_Array::value('is_test', $membershipParams, FALSE); $errors = $paymentResults = array(); $form->_values['isMembership'] = TRUE; - $isRecurForFirstTransaction = CRM_Utils_Array::value('is_recur', $form->_values, CRM_Utils_Array::value('is_recur', $membershipParams)); + $isRecurForFirstTransaction = CRM_Utils_Array::value('is_recur', $form->_params, CRM_Utils_Array::value('is_recur', $membershipParams)); $totalAmount = $membershipParams['amount']; diff --git a/CRM/Core/BAO/File.php b/CRM/Core/BAO/File.php index c5df5ec846d3..7b0ade3794b2 100644 --- a/CRM/Core/BAO/File.php +++ b/CRM/Core/BAO/File.php @@ -97,7 +97,7 @@ public static function filePostProcess( $mimeType = NULL ) { if (!$mimeType) { - CRM_Core_Error::fatal(ts('Mime Type is now a required parameter')); + CRM_Core_Error::statusBounce(ts('Mime Type is now a required parameter for file upload')); } $config = CRM_Core_Config::singleton(); @@ -116,7 +116,7 @@ public static function filePostProcess( CRM_Utils_File::createDir($directoryName); if (!rename($data, $directoryName . DIRECTORY_SEPARATOR . $filename)) { - CRM_Core_Error::fatal(ts('Could not move custom file to custom upload directory')); + CRM_Core_Error::statusBounce(ts('Could not move custom file to custom upload directory')); } // to get id's diff --git a/CRM/Core/Payment/PayPalProIPN.php b/CRM/Core/Payment/PayPalProIPN.php index e557541c362f..adac726bfa88 100644 --- a/CRM/Core/Payment/PayPalProIPN.php +++ b/CRM/Core/Payment/PayPalProIPN.php @@ -170,14 +170,6 @@ public function recur(&$input, &$ids, &$objects, $first) { return FALSE; } - if ($input['txnType'] == 'recurring_payment' && - $input['paymentStatus'] != 'Completed' - ) { - CRM_Core_Error::debug_log_message("Ignore all IPN payments that are not completed"); - echo "Failure: Invalid parameters
"; - return FALSE; - } - $recur = &$objects['contributionRecur']; // make sure the invoice ids match @@ -245,7 +237,19 @@ public function recur(&$input, &$ids, &$objects, $first) { $recur->start_date = $now; } else { - $recur->modified_date = $now; + $input['invoice_id'] = md5(uniqid(rand(), TRUE)); + $input['original_contribution_id'] = $ids['contribution']; + $input['contribution_recur_id'] = $ids['contributionRecur']; + + if ($input['paymentStatus'] != 'Completed') { + throw new CRM_Core_Exception("Ignore all IPN payments that are not completed"); + } + // In future moving to create pending & then complete, but this OK for now. + // Also consider accepting 'Failed' like other processors. + $input['contribution_status_id'] = 1; + + civicrm_api3('Contribution', 'repeattransaction', $input); + return; } //contribution installment is completed @@ -310,6 +314,7 @@ public function recur(&$input, &$ids, &$objects, $first) { $contribution->amount_level = $objects['contribution']->amount_level; $contribution->campaign_id = $objects['contribution']->campaign_id; $objects['contribution'] = &$contribution; + $contribution->invoice_id = md5(uniqid(rand(), TRUE)); } // CRM-13737 - am not aware of any reason why payment_date would not be set - this if is a belt & braces $objects['contribution']->receive_date = !empty($input['payment_date']) ? date('YmdHis', strtotime($input['payment_date'])) : $now; @@ -356,9 +361,6 @@ public function single(&$input, &$ids, &$objects, $recur = FALSE, $first = FALSE $transaction = new CRM_Core_Transaction(); - $participant = &$objects['participant']; - $membership = &$objects['membership']; - $status = $input['paymentStatus']; if ($status == 'Denied' || $status == 'Failed' || $status == 'Voided') { return $this->failed($objects, $transaction); diff --git a/CRM/Financial/BAO/FinancialTypeAccount.php b/CRM/Financial/BAO/FinancialTypeAccount.php index 828ba43ffd21..f26a3d9351d2 100644 --- a/CRM/Financial/BAO/FinancialTypeAccount.php +++ b/CRM/Financial/BAO/FinancialTypeAccount.php @@ -257,6 +257,7 @@ public static function createDefaultFinancialAccounts($financialType) { * * @param obj $financialTypeAccount of CRM_Financial_DAO_EntityFinancialAccount * + * @throws CRM_Core_Exception */ public static function validateRelationship($financialTypeAccount) { $financialAccountLinks = CRM_Financial_BAO_FinancialAccount::getfinancialAccountRelations(); @@ -266,7 +267,7 @@ public static function validateRelationship($financialTypeAccount) { $params = array( 1 => $accountRelationships[$financialTypeAccount->account_relationship], ); - throw new Exception(ts("This financial account cannot have '%1' relationship.", $params)); + throw new CRM_Core_Exception(ts("This financial account cannot have '%1' relationship.", $params)); } } diff --git a/CRM/Financial/Form/FinancialTypeAccount.php b/CRM/Financial/Form/FinancialTypeAccount.php index 7e63f87058ae..2055f5007975 100644 --- a/CRM/Financial/Form/FinancialTypeAccount.php +++ b/CRM/Financial/Form/FinancialTypeAccount.php @@ -300,8 +300,13 @@ public function postProcess() { if ($this->_action & CRM_Core_Action::ADD) { $params['entity_id'] = $this->_aid; } - $financialTypeAccount = CRM_Financial_BAO_FinancialTypeAccount::add($params, $ids); - CRM_Core_Session::setStatus(ts('The financial type Account has been saved.')); + try { + $financialTypeAccount = CRM_Financial_BAO_FinancialTypeAccount::add($params, $ids); + CRM_Core_Session::setStatus(ts('The financial type Account has been saved.'), ts('Saved'), 'success'); + } + catch (CRM_Core_Exception $e) { + CRM_Core_Error::statusBounce($e->getMessage()); + } } $buttonName = $this->controller->getButtonName(); diff --git a/CRM/Utils/DeprecatedUtils.php b/CRM/Utils/DeprecatedUtils.php index 934a175d1f9e..d720fb1ffec9 100644 --- a/CRM/Utils/DeprecatedUtils.php +++ b/CRM/Utils/DeprecatedUtils.php @@ -484,7 +484,9 @@ function _civicrm_api3_deprecated_check_contact_dedupe($params) { if ($field == NULL || $field === '') { continue; } - if (is_array($field)) { + // CRM-17040, Considering only primary contact when importing contributions. So contribution inserts into primary contact + // instead of soft credit contact. + if (is_array($field) && $key != "soft_credit") { foreach ($field as $value) { $break = FALSE; if (is_array($value)) { diff --git a/CRM/Utils/System/Backdrop.php b/CRM/Utils/System/Backdrop.php index a55dd9b126ed..ee79b0071f89 100644 --- a/CRM/Utils/System/Backdrop.php +++ b/CRM/Utils/System/Backdrop.php @@ -73,12 +73,12 @@ public function createUser(&$params, $mail) { // we also need to redirect b $config->inCiviCRM = TRUE; - $form = drupal_retrieve_form('user_register_form', $form_state); + $form = backdrop_retrieve_form('user_register_form', $form_state); $form_state['process_input'] = 1; $form_state['submitted'] = 1; $form['#array_parents'] = array(); $form['#tree'] = FALSE; - drupal_process_form('user_register_form', $form, $form_state); + backdrop_process_form('user_register_form', $form, $form_state); $config->inCiviCRM = FALSE; @@ -103,7 +103,7 @@ public function updateCMSName($ufID, $email) { } /** - * Check if username and email exists in the drupal db. + * Check if username and email exists in the Backdrop db. * * @param array $params * Array of name and mail values. @@ -115,7 +115,7 @@ public function updateCMSName($ufID, $email) { public static function checkUserNameEmailExists(&$params, &$errors, $emailName = 'email') { $errors = form_get_errors(); if ($errors) { - // unset drupal messages to avoid twice display of errors + // unset Backdrop messages to avoid twice display of errors unset($_SESSION['messages']); } @@ -164,7 +164,7 @@ public function setTitle($title, $pageTitle = NULL) { $pageTitle = $title; } - drupal_set_title($pageTitle, PASS_THROUGH); + backdrop_set_title($pageTitle, PASS_THROUGH); } } @@ -172,7 +172,7 @@ public function setTitle($title, $pageTitle = NULL) { * @inheritDoc */ public function appendBreadCrumb($breadCrumbs) { - $breadCrumb = drupal_get_breadcrumb(); + $breadCrumb = backdrop_get_breadcrumb(); if (is_array($breadCrumbs)) { foreach ($breadCrumbs as $crumbs) { @@ -190,7 +190,7 @@ public function appendBreadCrumb($breadCrumbs) { $breadCrumb[] = "{$crumbs['title']}"; } } - drupal_set_breadcrumb($breadCrumb); + backdrop_set_breadcrumb($breadCrumb); } /** @@ -198,7 +198,7 @@ public function appendBreadCrumb($breadCrumbs) { */ public function resetBreadCrumb() { $bc = array(); - drupal_set_breadcrumb($bc); + backdrop_set_breadcrumb($bc); } /** @@ -212,7 +212,7 @@ public function addHTMLHead($header) { '#type' => 'markup', '#markup' => $header, ); - drupal_add_html_head($data, $key); + backdrop_add_html_head($data, $key); } } @@ -230,9 +230,9 @@ public function addScriptUrl($url, $region) { default: return FALSE; } - // If the path is within the drupal directory we can use the more efficient 'file' setting + // If the path is within the Backdrop directory we can use the more efficient 'file' setting $params['type'] = $this->formatResourceUrl($url) ? 'file' : 'external'; - drupal_add_js($url, $params); + backdrop_add_js($url, $params); return TRUE; } @@ -250,7 +250,7 @@ public function addScript($code, $region) { default: return FALSE; } - drupal_add_js($code, $params); + backdrop_add_js($code, $params); return TRUE; } @@ -262,9 +262,9 @@ public function addStyleUrl($url, $region) { return FALSE; } $params = array(); - // If the path is within the drupal directory we can use the more efficient 'file' setting + // If the path is within the Backdrop directory we can use the more efficient 'file' setting $params['type'] = $this->formatResourceUrl($url) ? 'file' : 'external'; - drupal_add_css($url, $params); + backdrop_add_css($url, $params); return TRUE; } @@ -276,7 +276,7 @@ public function addStyle($code, $region) { return FALSE; } $params = array('type' => 'inline'); - drupal_add_css($code, $params); + backdrop_add_css($code, $params); return TRUE; } @@ -331,7 +331,7 @@ public function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realP } else { // CRM-8638 - // SOAP cannot load drupal bootstrap and hence we do it the old way + // SOAP cannot load Backdrop bootstrap and hence we do it the old way // Contact CiviSMTP folks if we run into issues with this :) $cmsPath = $this->cmsRootPath(); @@ -414,8 +414,8 @@ public function userLoginFinalize($params = array()) { * @inheritDoc */ public function getUFLocale() { - // return CiviCRM’s xx_YY locale that either matches Drupal’s Chinese locale - // (for CRM-6281), Drupal’s xx_YY or is retrieved based on Drupal’s xx + // return CiviCRM’s xx_YY locale that either matches Backdrop’s Chinese locale + // (for CRM-6281), Backdrop’s xx_YY or is retrieved based on Backdrop’s xx // sometimes for CLI based on order called, this might not be set and/or empty global $language; @@ -515,11 +515,11 @@ public function loadBootStrap($params = array(), $loadUser = TRUE, $throwError = } return FALSE; } - // load drupal bootstrap + // load Backdrop bootstrap chdir($cmsPath); define('BACKDROP_ROOT', $cmsPath); - // For drupal multi-site CRM-11313 + // For Backdrop multi-site CRM-11313 if ($realPath && strpos($realPath, 'sites/all/modules/') === FALSE) { preg_match('@sites/([^/]*)/modules@s', $realPath, $matches); if (!empty($matches[1])) { @@ -890,4 +890,130 @@ public function permissionEmails($permissionName) { return array(); } + /** + * @inheritdoc + */ + public function getDefaultFileStorage() { + $config = CRM_Core_Config::singleton(); + $baseURL = CRM_Utils_System::languageNegotiationURL($config->userFrameworkBaseURL, FALSE, TRUE); + + $siteName = $this->parseBackdropSiteNameFromRequest('/files/civicrm'); + if ($siteName) { + $filesURL = $baseURL . "sites/$siteName/files/civicrm/"; + } + else { + $filesURL = $baseURL . "files/civicrm/"; + } + + return array( + 'url' => $filesURL, + 'path' => CRM_Utils_File::baseFilePath(), + ); + } + + /** + * Check if a resource url is within the Backdrop directory and format appropriately. + * + * @param $url (reference) + * + * @return bool + * TRUE for internal paths, FALSE for external. The backdrop_add_js fn is able to add js more + * efficiently if it is known to be in the Backdrop site + */ + public function formatResourceUrl(&$url) { + $internal = FALSE; + $base = CRM_Core_Config::singleton()->resourceBase; + global $base_url; + // Handle absolute urls + // compares $url (which is some unknown/untrusted value from a third-party dev) to the CMS's base url (which is independent of civi's url) + // to see if the url is within our Backdrop dir, if it is we are able to treated it as an internal url + if (strpos($url, $base_url) === 0) { + $file = trim(str_replace($base_url, '', $url), '/'); + // CRM-18130: Custom CSS URL not working if aliased or rewritten + if (file_exists(BACKDROP_ROOT . $file)) { + $url = $file; + $internal = TRUE; + } + } + // Handle relative urls that are within the CiviCRM module directory + elseif (strpos($url, $base) === 0) { + $internal = TRUE; + $url = $this->appendCoreDirectoryToResourceBase(dirname(backdrop_get_path('module', 'civicrm')) . '/') . trim(substr($url, strlen($base)), '/'); + } + // Strip query string + $q = strpos($url, '?'); + if ($q && $internal) { + $url = substr($url, 0, $q); + } + return $internal; + } + + /** + * @inheritDoc + */ + public function setMessage($message) { + backdrop_set_message($message); + } + + /** + * @inheritDoc + */ + public function permissionDenied() { + backdrop_access_denied(); + } + + /** + * @inheritDoc + */ + public function flush() { + backdrop_flush_all_caches(); + } + + /** + * Determine if Backdrop multi-site applies to the current request -- and, + * specifically, determine the name of the multisite folder. + * + * @param string $flagFile + * Check if $flagFile exists inside the site dir. + * @return null|string + * string, e.g. `bar.example.com` if using multisite. + * NULL if using the default site. + */ + private function parseBackdropSiteNameFromRequest($flagFile = '') { + $phpSelf = array_key_exists('PHP_SELF', $_SERVER) ? $_SERVER['PHP_SELF'] : ''; + $httpHost = array_key_exists('HTTP_HOST', $_SERVER) ? $_SERVER['HTTP_HOST'] : ''; + if (empty($httpHost)) { + $httpHost = parse_url(CIVICRM_UF_BASEURL, PHP_URL_HOST); + if (parse_url(CIVICRM_UF_BASEURL, PHP_URL_PORT)) { + $httpHost .= ':' . parse_url(CIVICRM_UF_BASEURL, PHP_URL_PORT); + } + } + + $confdir = $this->cmsRootPath() . '/sites'; + + if (file_exists($confdir . "/sites.php")) { + include $confdir . "/sites.php"; + } + else { + $sites = array(); + } + + $uri = explode('/', $phpSelf); + $server = explode('.', implode('.', array_reverse(explode(':', rtrim($httpHost, '.'))))); + for ($i = count($uri) - 1; $i > 0; $i--) { + for ($j = count($server); $j > 0; $j--) { + $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i)); + if (file_exists("$confdir/$dir" . $flagFile)) { + \Civi::$statics[__CLASS__]['drupalSiteName'] = $dir; + return \Civi::$statics[__CLASS__]['drupalSiteName']; + } + // check for alias + if (isset($sites[$dir]) && file_exists("$confdir/{$sites[$dir]}" . $flagFile)) { + \Civi::$statics[__CLASS__]['drupalSiteName'] = $sites[$dir]; + return \Civi::$statics[__CLASS__]['drupalSiteName']; + } + } + } + } + } diff --git a/Civi/Core/SettingsStack.php b/Civi/Core/SettingsStack.php index 79e2f22d7a84..434c8371e6b6 100644 --- a/Civi/Core/SettingsStack.php +++ b/Civi/Core/SettingsStack.php @@ -4,7 +4,12 @@ /** * Class SettingsStack * - * The settings stack allows you to temporarily apply settings. + * The settings stack allows you to temporarily change (then restore) settings. It's intended + * primarily for use in testing. + * + * Like the global `$civicrm_setting` variable, it works best with typical inert settings that + * do not trigger extra activation logic. A handful of settings (such as `enable_components` + * and ~5 others) * * @package Civi\Core */ diff --git a/ang/crmMailing/Recipients.js b/ang/crmMailing/Recipients.js index d9714d48e696..dfb70b349314 100644 --- a/ang/crmMailing/Recipients.js +++ b/ang/crmMailing/Recipients.js @@ -8,7 +8,6 @@ scope: { ngRequired: '@' }, - templateUrl: '~/crmMailing/Recipients.html', link: function(scope, element, attrs, ngModel) { scope.recips = ngModel.$viewValue; scope.groups = scope.$parent.$eval(attrs.crmAvailGroups); diff --git a/api/v3/RelationshipType.php b/api/v3/RelationshipType.php index 30f238692a1e..4260edc42cac 100644 --- a/api/v3/RelationshipType.php +++ b/api/v3/RelationshipType.php @@ -77,8 +77,6 @@ function civicrm_api3_relationship_type_create($params) { * Array of parameters determined by getfields. */ function _civicrm_api3_relationship_type_create_spec(&$params) { - $params['contact_type_a']['api.required'] = 1; - $params['contact_type_b']['api.required'] = 1; $params['name_a_b']['api.required'] = 1; $params['name_b_a']['api.required'] = 1; $params['is_active']['api.default'] = 1; diff --git a/api/v3/examples/Setting/GetFields.php b/api/v3/examples/Setting/GetFields.php index 739f9d4814c1..3d2c08eaf8b3 100644 --- a/api/v3/examples/Setting/GetFields.php +++ b/api/v3/examples/Setting/GetFields.php @@ -40,7 +40,7 @@ function setting_getfields_expectedresult() { $expectedResult = array( 'is_error' => 0, 'version' => 3, - 'count' => 151, + 'count' => 157, 'values' => array( 'address_standardization_provider' => array( 'group_name' => 'Address Preferences', @@ -127,6 +127,63 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => 'If set, new contacts that are created when signing a petition are assigned a tag of this name.', ), + 'civicaseRedactActivityEmail' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'civicaseRedactActivityEmail', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array(), + 'default' => 'default', + 'add' => '4.7', + 'title' => 'Redact Activity Email', + 'is_domain' => 1, + 'is_contact' => 0, + 'pseudoconstant' => array( + 'callback' => 'CRM_Case_Info::getRedactOptions', + ), + 'description' => 'Should activity emails be redacted? (Set \"Default\" to load setting from the legacy \"Settings.xml\" file.)', + 'help_text' => '', + ), + 'civicaseAllowMultipleClients' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'civicaseAllowMultipleClients', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array(), + 'default' => 'default', + 'add' => '4.7', + 'title' => 'Allow Multiple Case Clients', + 'is_domain' => 1, + 'is_contact' => 0, + 'pseudoconstant' => array( + 'callback' => 'CRM_Case_Info::getMultiClientOptions', + ), + 'description' => 'How many clients may be associated with a given case? (Set \"Default\" to load setting from the legacy \"Settings.xml\" file.)', + 'help_text' => '', + ), + 'civicaseNaturalActivityTypeSort' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'civicaseNaturalActivityTypeSort', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array(), + 'default' => 'default', + 'add' => '4.7', + 'title' => 'Activity Type Sorting', + 'is_domain' => 1, + 'is_contact' => 0, + 'pseudoconstant' => array( + 'callback' => 'CRM_Case_Info::getSortOptions', + ), + 'description' => 'How to sort activity-types on the \"Manage Case\" screen? (Set \"Default\" to load setting from the legacy \"Settings.xml\" file.)', + 'help_text' => '', + ), 'cvv_backoffice_required' => array( 'group_name' => 'Contribute Preferences', 'group' => 'contribute', @@ -667,6 +724,27 @@ function setting_getfields_expectedresult() { 'description' => 'If enabled, CiviCRM sends PDF receipt as an attachment during event signup or online contribution.', 'help_text' => '', ), + 'recordGeneratedLetters' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'recordGeneratedLetters', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array( + 'class' => 'crm-select2', + ), + 'default' => 'multiple', + 'add' => '4.7', + 'title' => 'Record generated letters', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'When generating a letter (PDF/Word) via mail-merge, how should the letter be recorded?', + 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => 'CRM_Contact_Form_Task_PDFLetterCommon::getLoggingOptions', + ), + ), 'wkhtmltopdfPath' => array( 'group_name' => 'CiviCRM Preferences', 'group' => 'core', @@ -1162,6 +1240,39 @@ function setting_getfields_expectedresult() { 'description' => 'If enabled, then CMS email id will be syncronised with CiviCRM contacts\'s primary email.', 'help_text' => '', ), + 'preserve_activity_tab_filter' => array( + 'group_name' => 'CiviCRM Preferences', + 'group' => 'core', + 'name' => 'preserve_activity_tab_filter', + 'type' => 'String', + 'html_type' => 'Text', + 'default' => 0, + 'add' => '4.7', + 'title' => 'Preserve activity filters as a user preference', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'When enabled, any filter settings a user selects on the contact\'s Activity tab will be remembered as they visit other contacts', + 'help_text' => '', + ), + 'assetCache' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'assetCache', + 'type' => 'String', + 'quick_form_type' => 'Select', + 'html_type' => 'Select', + 'html_attributes' => array(), + 'default' => 'auto', + 'add' => '4.7', + 'title' => 'Asset Caching', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'Store computed JS/CSS content in cache files? (Note: In \"Auto\" mode, the \"Debug\" setting will determine whether to activate the cache.)', + 'help_text' => '', + 'pseudoconstant' => array( + 'callback' => '\Civi\Core\AssetBuilder::getCacheModes', + ), + ), 'userFrameworkLogging' => array( 'group_name' => 'Developer Preferences', 'group' => 'developer', @@ -1467,6 +1578,9 @@ function setting_getfields_expectedresult() { 'pseudoconstant' => array( 'callback' => 'CRM_Admin_Form_Setting_Localization::getCurrencySymbols', ), + 'on_change' => array( + '0' => 'CRM_Admin_Form_Setting_Localization::onChangeDefaultCurrency', + ), ), 'defaultContactCountry' => array( 'group_name' => 'Localization Preferences', @@ -2143,6 +2257,24 @@ function setting_getfields_expectedresult() { 'description' => '', 'help_text' => '', ), + 'simple_mail_limit' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'simple_mail_limit', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 50, + 'title' => 'Simple mail limit', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'The number of emails sendable via simple mail. Make sure you understand the implications for your spam reputation and legal requirements for bulk emails before editing. As there is some risk both to your spam reputation and the products if this is misused it is a hidden setting', + 'help_text' => 'CiviCRM forces users sending more than this number of mails to use CiviMails. CiviMails have additional precautions: not sending to contacts who do not want bulk mail, adding domain name and opt out links. You should familiarise yourself with the law relevant to you on bulk mailings if changing this setting. For the US https://en.wikipedia.org/wiki/CAN-SPAM_Act_of_2003 is a good place to start.', + ), 'geoAPIKey' => array( 'add' => '4.7', 'help_text' => '', @@ -2456,6 +2588,20 @@ function setting_getfields_expectedresult() { 'description' => 'If set, this will be the default profile used for contact search.', 'help_text' => '', ), + 'searchPrimaryDetailsOnly' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'searchPrimaryDetailsOnly', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.7', + 'title' => 'Search Primary Details Only', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, only primary details (eg contact\'s primary email, phone, etc) will be included in Basic and Advanced Search results. Disabling this feature will allow users to match contacts using any email, phone etc detail.', + 'help_text' => '', + ), 'userFrameworkResourceURL' => array( 'bootstrap_comment' => 'This is a boot setting which may be loaded during bootstrap. Defaults are loaded via SettingsBag::getSystemDefaults().', 'group' => 'url', diff --git a/settings/Mailing.setting.php b/settings/Mailing.setting.php index 056122f764bc..1969df133aea 100644 --- a/settings/Mailing.setting.php +++ b/settings/Mailing.setting.php @@ -315,4 +315,22 @@ 'description' => NULL, 'help_text' => NULL, ), + 'simple_mail_limit' => array( + 'group_name' => 'Mailing Preferences', + 'group' => 'mailing', + 'name' => 'simple_mail_limit', + 'type' => 'Integer', + 'quick_form_type' => 'Element', + 'html_type' => 'text', + 'html_attributes' => array( + 'size' => 4, + 'maxlength' => 8, + ), + 'default' => 50, + 'title' => 'Simple mail limit', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'The number of emails sendable via simple mail. Make sure you understand the implications for your spam reputation and legal requirements for bulk emails before editing. As there is some risk both to your spam reputation and the products if this is misused it is a hidden setting', + 'help_text' => 'CiviCRM forces users sending more than this number of mails to use CiviMails. CiviMails have additional precautions: not sending to contacts who do not want bulk mail, adding domain name and opt out links. You should familiarise yourself with the law relevant to you on bulk mailings if changing this setting. For the US https://en.wikipedia.org/wiki/CAN-SPAM_Act_of_2003 is a good place to start.', + ), ); diff --git a/tests/phpunit/CRM/Contribute/Import/Parser/ContributionTest.php b/tests/phpunit/CRM/Contribute/Import/Parser/ContributionTest.php new file mode 100644 index 000000000000..303bdd11138e --- /dev/null +++ b/tests/phpunit/CRM/Contribute/Import/Parser/ContributionTest.php @@ -0,0 +1,85 @@ + 'Contact', + 'last_name' => 'One', + 'external_identifier' => 'ext-1', + 'contact_type' => 'Individual', + ); + $contact2Params = array( + 'first_name' => 'Contact', + 'last_name' => 'Two', + 'external_identifier' => 'ext-2', + 'contact_type' => 'Individual', + ); + $contact1Id = $this->individualCreate($contact1Params); + $contact2Id = $this->individualCreate($contact2Params); + $values = array( + "total_amount" => 10, + "financial_type" => "Donation", + "external_identifier" => "ext-1", + "soft_credit" => "ext-2", + ); + $mapperSoftCredit = array(NULL, NULL, NULL, "external_identifier"); + $mapperSoftCreditType = array(NULL, NULL, NULL, "1"); + $this->runImport($values, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Contribute_Import_Parser::SOFT_CREDIT, $mapperSoftCredit, NULL, $mapperSoftCreditType); + $params = array( + "contact_id" => $contact1Id, + ); + $values = array(); + $contributionsOfMainContact = CRM_Contribute_BAO_Contribution::retrieve($params, $values, $values); + $params["contact_id"] = $contact2Id; + $contributionsOfSoftContact = CRM_Contribute_BAO_ContributionSoft::retrieve($params, $values); + $this->assertEquals(1, count($contributionsOfMainContact), 'Contribution not added for primary contact'); + $this->assertEquals(1, count($contributionsOfSoftContact), 'Soft Contribution not added for secondary contact'); + } + /** + * Run the import parser. + * + * @param array $originalValues + * + * @param int $onDuplicateAction + * @param int $expectedResult + * @param array|null $mapperSoftCredit + * @param array|null $mapperPhoneType + * @param array|null $mapperSoftCreditType + * @param array|null $fields + * Array of field names. Will be calculated from $originalValues if not passed in. + */ + protected function runImport($originalValues, $onDuplicateAction, $expectedResult, $mapperSoftCredit = NULL, $mapperPhoneType = NULL, $mapperSoftCreditType = NULL, $fields = NULL) { + if (!$fields) { + $fields = array_keys($originalValues); + } + $values = array_values($originalValues); + $parser = new CRM_Contribute_Import_Parser_Contribution($fields, $mapperSoftCredit, $mapperPhoneType, $mapperSoftCreditType); + $parser->_contactType = 'Individual'; + $parser->init(); + $this->assertEquals($expectedResult, $parser->import($onDuplicateAction, $values), 'Return code from parser import was not as expected'); + } + +} diff --git a/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php b/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php index e51ff0141ac1..786557a97266 100644 --- a/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php +++ b/tests/phpunit/CRM/Core/Payment/PayPalProIPNTest.php @@ -95,6 +95,7 @@ public function testIPNPaymentRecurSuccess() { )); $this->assertEquals(2, $contribution['count']); $this->assertEquals('secondone', $contribution['values'][1]['trxn_id']); + $this->assertEquals('Debit Card', $contribution['values'][1]['payment_instrument']); } /** diff --git a/tests/phpunit/Civi/Core/SettingsStackTest.php b/tests/phpunit/Civi/Core/SettingsStackTest.php new file mode 100644 index 000000000000..ac4cee90567b --- /dev/null +++ b/tests/phpunit/Civi/Core/SettingsStackTest.php @@ -0,0 +1,33 @@ +useTransaction(TRUE); + } + + public function tearDown() { + parent::tearDown(); + } + + /** + * Temporarily modify -- then restore -- settings. + */ + public function testStack() { + $origVal = \Civi::settings()->get('show_events'); + + $settingsStack = new \Civi\Core\SettingsStack(); + + $settingsStack->push('show_events', 9); + $this->assertEquals(9, \Civi::settings()->get('show_events')); + + $settingsStack->push('show_events', 8); + $this->assertEquals(8, \Civi::settings()->get('show_events')); + + $settingsStack->popAll(); + $this->assertEquals($origVal, \Civi::settings()->get('show_events')); + } + +} diff --git a/tests/phpunit/api/v3/ContributionPageTest.php b/tests/phpunit/api/v3/ContributionPageTest.php index 1e059b076b21..13d56d020d3e 100644 --- a/tests/phpunit/api/v3/ContributionPageTest.php +++ b/tests/phpunit/api/v3/ContributionPageTest.php @@ -1202,14 +1202,50 @@ public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed( $this->assertEquals(2, $recurringContribution['contribution_status_id']); } + /** + * Test non-recur contribution with membership payment + */ + public function testSubmitMembershipIsSeparatePaymentNotRecur() { + //Create recur contribution page. + $this->setUpMembershipContributionPage(TRUE, TRUE); + $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor); + $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success')); + + //Sumbit payment with recur disabled. + $submitParams = array( + 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']), + 'id' => (int) $this->_ids['contribution_page'], + 'amount' => 10, + 'frequency_interval' => 1, + 'frequency_unit' => 'month', + 'billing_first_name' => 'Billy', + 'billing_middle_name' => 'Goat', + 'billing_last_name' => 'Gruff', + 'email' => 'billy@goat.gruff', + 'selectMembership' => $this->_ids['membership_type'], + 'payment_processor_id' => 1, + 'credit_card_number' => '4111111111111111', + 'credit_card_type' => 'Visa', + 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040), + 'cvv2' => 123, + ); + + //Assert if recur contribution is created. + $this->callAPISuccess('contribution_page', 'submit', $submitParams); + $recur = $this->callAPISuccess('contribution_recur', 'get', array()); + $this->assertEmpty($recur['count']); + } + + /** * Set up membership contribution page. * @param bool $isSeparatePayment + * @param bool $isRecur */ - public function setUpMembershipContributionPage($isSeparatePayment = FALSE) { + public function setUpMembershipContributionPage($isSeparatePayment = FALSE, $isRecur = FALSE) { $this->setUpMembershipBlockPriceSet(); $this->setupPaymentProcessor(); - $this->setUpContributionPage(); + $this->setUpContributionPage($isRecur); $this->callAPISuccess('membership_block', 'create', array( 'entity_id' => $this->_ids['contribution_page'], @@ -1334,8 +1370,13 @@ public function addOtherAmountFieldToMembershipPriceSet() { /** * Help function to set up contribution page with some defaults. + * @param bool $isRecur */ - public function setUpContributionPage() { + public function setUpContributionPage($isRecur = FALSE) { + if ($isRecur) { + $this->params['is_recur'] = 1; + $this->params['recur_frequency_unit'] = 'month'; + } $contributionPageResult = $this->callAPISuccess($this->_entity, 'create', $this->params); if (empty($this->_ids['price_set'])) { $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams); diff --git a/tests/phpunit/api/v3/RelationshipTypeTest.php b/tests/phpunit/api/v3/RelationshipTypeTest.php index 24e44e109de5..1b6ad286e4cb 100644 --- a/tests/phpunit/api/v3/RelationshipTypeTest.php +++ b/tests/phpunit/api/v3/RelationshipTypeTest.php @@ -93,19 +93,6 @@ public function testRelationshipTypeCreateWithoutName() { ); } - /** - * Check with no contact type. - */ - public function testRelationshipTypeCreateWithoutContactType() { - $relTypeParams = array( - 'name_a_b' => 'Relation 1 without contact type', - 'name_b_a' => 'Relation 2 without contact type', - ); - $result = $this->callAPIFailure('relationship_type', 'create', $relTypeParams, - 'Mandatory key(s) missing from params array: contact_type_a, contact_type_b' - ); - } - /** * Create relationship type. */ @@ -190,7 +177,7 @@ public function testRelationshipTypeDelete() { public function testRelationshipTypeUpdateEmpty() { $params = array(); $result = $this->callAPIFailure('relationship_type', 'create', $params); - $this->assertEquals($result['error_message'], 'Mandatory key(s) missing from params array: name_a_b, name_b_a, contact_type_a, contact_type_b'); + $this->assertEquals($result['error_message'], 'Mandatory key(s) missing from params array: name_a_b, name_b_a'); } /** diff --git a/xml/schema/Contact/Contact.xml b/xml/schema/Contact/Contact.xml index 4b2aab12f81b..428dc40b55ad 100644 --- a/xml/schema/Contact/Contact.xml +++ b/xml/schema/Contact/Contact.xml @@ -534,6 +534,9 @@