/** * Create test generated example in api/v3/examples. * * To turn this off (e.g. on the server) set * define(DONT_DOCUMENT_TEST_CONFIG ,1); * in your settings file * * @param string $entity * @param string $action * @param array $params * Array as passed to civicrm_api function. * @param array $result * Array as received from the civicrm_api function. * @param string $testFunction * Calling function - generally __FUNCTION__. * @param string $testFile * Called from file - generally __FILE__. * @param string $description * Descriptive text for the example file. * @param string $exampleName * Name for this example file (CamelCase) - if omitted the action name will be substituted. */ private function documentMe($entity, $action, $params, $result, $testFunction, $testFile, $description = "", $exampleName = NULL) { if (defined('DONT_DOCUMENT_TEST_CONFIG') && DONT_DOCUMENT_TEST_CONFIG) { return; } $entity = _civicrm_api_get_camel_name($entity); $action = strtolower($action); if (empty($exampleName)) { // Attempt to convert lowercase action name to CamelCase. // This is clunky/imperfect due to the convention of all lowercase actions. $exampleName = CRM_Utils_String::convertStringToCamel($action); $knownPrefixes = array('Get', 'Set', 'Create', 'Update', 'Send'); foreach ($knownPrefixes as $prefix) { if (strpos($exampleName, $prefix) === 0 && $prefix != $exampleName) { $exampleName[strlen($prefix)] = strtoupper($exampleName[strlen($prefix)]); } } } $this->tidyExampleResult($result); if (isset($params['version'])) { unset($params['version']); } // Format multiline description as array $desc = array(); if (is_string($description) && strlen($description)) { foreach (explode("\n", $description) as $line) { $desc[] = trim($line); } } $smarty = CRM_Core_Smarty::singleton(); $smarty->assign('testFunction', $testFunction); $smarty->assign('function', _civicrm_api_get_entity_name_from_camel($entity) . "_{$action}"); $smarty->assign('params', $params); $smarty->assign('entity', $entity); $smarty->assign('testFile', basename($testFile)); $smarty->assign('description', $desc); $smarty->assign('result', $result); $smarty->assign('action', $action); global $civicrm_root; if (file_exists($civicrm_root . '/tests/templates/documentFunction.tpl')) { if (!is_dir($civicrm_root . "/api/v3/examples/{$entity}")) { mkdir($civicrm_root . "/api/v3/examples/{$entity}"); } $f = fopen($civicrm_root . "/api/v3/examples/{$entity}/{$exampleName}.php", "w+b"); fwrite($f, $smarty->fetch($civicrm_root . '/tests/templates/documentFunction.tpl')); fclose($f); } }
/** * Build the form object. */ public function buildQuickForm() { //@todo document the purpose of cdType (if still in use) if ($this->_cdType) { CRM_Custom_Form_CustomData::buildQuickForm($this); return; } $allPanes = array(); //tax rate from financialType $this->assign('taxRates', json_encode(CRM_Core_PseudoConstant::getTaxRates())); $this->assign('currencies', json_encode(CRM_Core_OptionGroup::values('currencies_enabled'))); // build price set form. $buildPriceSet = FALSE; $invoiceSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings); $this->assign('invoicing', $invoicing); // display tax amount on edit contribution page if ($invoicing && $this->_action & CRM_Core_Action::UPDATE && isset($this->_values['tax_amount'])) { $this->assign('totalTaxAmount', $this->_values['tax_amount']); } if (empty($this->_lineItems) && ($this->_priceSetId || !empty($_POST['price_set_id']))) { $buildPriceSet = TRUE; $getOnlyPriceSetElements = TRUE; if (!$this->_priceSetId) { $this->_priceSetId = $_POST['price_set_id']; $getOnlyPriceSetElements = FALSE; } $this->set('priceSetId', $this->_priceSetId); CRM_Price_BAO_PriceSet::buildPriceSet($this); // get only price set form elements. if ($getOnlyPriceSetElements) { return; } } // use to build form during form rule. $this->assign('buildPriceSet', $buildPriceSet); $showAdditionalInfo = FALSE; $defaults = $this->_values; $additionalDetailFields = array('note', 'thankyou_date', 'invoice_id', 'non_deductible_amount', 'fee_amount', 'net_amount'); foreach ($additionalDetailFields as $key) { if (!empty($defaults[$key])) { $defaults['hidden_AdditionalDetail'] = 1; break; } } if ($this->_productDAO) { if ($this->_productDAO->product_id) { $defaults['hidden_Premium'] = 1; } } if ($this->_noteID && isset($this->_values['note'])) { $defaults['hidden_AdditionalDetail'] = 1; } $paneNames = array(ts('Additional Details') => 'AdditionalDetail'); //Add Premium pane only if Premium is exists. $dao = new CRM_Contribute_DAO_Product(); $dao->is_active = 1; if ($dao->find(TRUE)) { $paneNames[ts('Premium Information')] = 'Premium'; } $billingPanes = array(); if ($this->_mode) { if (CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE) == TRUE) { $buildRecurBlock = TRUE; foreach ($this->billingPane as $name => $label) { if (!empty($this->billingFieldSets[$name]['fields'])) { // @todo reduce variation so we don't have to convert 'credit_card' to 'CreditCard' $billingPanes[$label] = $this->generatePane(CRM_Utils_String::convertStringToCamel($name), $defaults); } } } } foreach ($paneNames as $name => $type) { $allPanes[$name] = $this->generatePane($type, $defaults); } if (empty($this->_recurPaymentProcessors)) { $buildRecurBlock = FALSE; } if ($buildRecurBlock) { CRM_Contribute_Form_Contribution_Main::buildRecur($this); $this->setDefaults(array('is_recur' => 0)); } $this->assign('buildRecurBlock', $buildRecurBlock); $qfKey = $this->controller->_key; $this->assign('qfKey', $qfKey); $this->assign('billingPanes', $billingPanes); $this->assign('allPanes', $allPanes); $this->addFormRule(array('CRM_Contribute_Form_Contribution', 'formRule'), $this); if ($this->_formType) { $this->assign('formType', $this->_formType); return; } $this->applyFilter('__ALL__', 'trim'); if ($this->_action & CRM_Core_Action::DELETE) { $this->addButtons(array(array('type' => 'next', 'name' => ts('Delete'), 'spacing' => ' ', 'isDefault' => TRUE), array('type' => 'cancel', 'name' => ts('Cancel')))); return; } //need to assign custom data type and subtype to the template $this->assign('customDataType', 'Contribution'); $this->assign('customDataSubType', $this->_contributionType); $this->assign('entityID', $this->_id); if ($this->_context == 'standalone') { $this->addEntityRef('contact_id', ts('Contact'), array('create' => TRUE, 'api' => array('extra' => array('email'))), TRUE); } $attributes = CRM_Core_DAO::getAttribute('CRM_Contribute_DAO_Contribution'); $financialType = $this->add('select', 'financial_type_id', ts('Financial Type'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::financialType(), TRUE, array('onChange' => "CRM.buildCustomData( 'Contribution', this.value );")); $paymentInstrument = FALSE; if (!$this->_mode) { $paymentInstrument = $this->add('select', 'payment_instrument_id', ts('Paid By'), array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::paymentInstrument(), TRUE, array('onChange' => "return showHideByValue('payment_instrument_id','4','checkNumber','table-row','select',false);")); } $trxnId = $this->add('text', 'trxn_id', ts('Transaction ID'), array('class' => 'twelve') + $attributes['trxn_id']); //add receipt for offline contribution $this->addElement('checkbox', 'is_email_receipt', ts('Send Receipt?')); $this->add('select', 'from_email_address', ts('Receipt From'), $this->_fromEmails); $status = CRM_Contribute_PseudoConstant::contributionStatus(); // suppressing contribution statuses that are NOT relevant to pledges (CRM-5169) $statusName = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); if ($this->_ppID) { foreach (array('Cancelled', 'Failed', 'In Progress') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } } elseif (!$this->_ppID && $this->_id || !$this->_id) { $suppressFlag = FALSE; if ($this->_id) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (CRM_Utils_Array::value('membership', $componentDetails) || CRM_Utils_Array::value('participant', $componentDetails)) { $suppressFlag = TRUE; } } if (!$suppressFlag) { foreach (array('Overdue', 'In Progress') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } } else { unset($status[CRM_Utils_Array::key('Overdue', $statusName)]); } } if ($this->_id) { $contributionStatus = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_id, 'contribution_status_id'); $name = CRM_Utils_Array::value($contributionStatus, $statusName); switch ($name) { case 'Completed': case 'Cancelled': case 'Refunded': unset($status[CRM_Utils_Array::key('In Progress', $statusName)]); unset($status[CRM_Utils_Array::key('Pending', $statusName)]); unset($status[CRM_Utils_Array::key('Failed', $statusName)]); break; case 'Pending': case 'In Progress': unset($status[CRM_Utils_Array::key('Refunded', $statusName)]); break; case 'Failed': foreach (array('Pending', 'Refunded', 'Completed', 'In Progress', 'Cancelled') as $suppress) { unset($status[CRM_Utils_Array::key($suppress, $statusName)]); } break; } } else { unset($status[CRM_Utils_Array::key('Refunded', $statusName)]); } $this->add('select', 'contribution_status_id', ts('Contribution Status'), $status, FALSE); // add various dates $this->addDateTime('receive_date', ts('Received'), FALSE, array('formatType' => 'activityDateTime')); if ($this->_online) { $this->assign('hideCalender', TRUE); } $checkNumber = $this->add('text', 'check_number', ts('Check Number'), $attributes['check_number']); $this->addDateTime('receipt_date', ts('Receipt Date'), FALSE, array('formatType' => 'activityDateTime')); $this->addDateTime('cancel_date', ts('Cancelled / Refunded Date'), FALSE, array('formatType' => 'activityDateTime')); $this->add('textarea', 'cancel_reason', ts('Cancellation / Refund Reason'), $attributes['cancel_reason']); $recurJs = NULL; if ($buildRecurBlock) { $recurJs = array('onChange' => "buildRecurBlock( this.value ); return false;"); } $element = $this->add('select', 'payment_processor_id', ts('Payment Processor'), $this->_processors, NULL, $recurJs); if ($this->_online) { $element->freeze(); } $totalAmount = NULL; if (empty($this->_lineItems)) { $buildPriceSet = FALSE; $priceSets = CRM_Price_BAO_PriceSet::getAssoc(FALSE, 'CiviContribute'); if (!empty($priceSets) && !$this->_ppID) { $buildPriceSet = TRUE; } // don't allow price set for contribution if it is related to participant, or if it is a pledge payment // and if we already have line items for that participant. CRM-5095 if ($buildPriceSet && $this->_id) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); $pledgePaymentId = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment', $this->_id, 'id', 'contribution_id'); if ($pledgePaymentId) { $buildPriceSet = FALSE; } if ($participantID = CRM_Utils_Array::value('participant', $componentDetails)) { $participantLI = CRM_Price_BAO_LineItem::getLineItems($participantID); if (!CRM_Utils_System::isNull($participantLI)) { $buildPriceSet = FALSE; } } } $hasPriceSets = FALSE; if ($buildPriceSet) { $hasPriceSets = TRUE; $element = $this->add('select', 'price_set_id', ts('Choose price set'), array('' => ts('Choose price set')) + $priceSets, NULL, array('onchange' => "buildAmount( this.value );")); if ($this->_online && !($this->_action & CRM_Core_Action::UPDATE)) { $element->freeze(); } } $this->assign('hasPriceSets', $hasPriceSets); $currencyFreeze = FALSE; if (!($this->_action & CRM_Core_Action::UPDATE)) { if ($this->_online || $this->_ppID) { $attributes['total_amount'] = array_merge($attributes['total_amount'], array('READONLY' => TRUE, 'style' => "background-color:#EBECE4")); $optionTypes = array('1' => ts('Adjust Pledge Payment Schedule?'), '2' => ts('Adjust Total Pledge Amount?')); $this->addRadio('option_type', NULL, $optionTypes, array(), '<br/>'); $currencyFreeze = TRUE; } } $totalAmount = $this->addMoney('total_amount', ts('Total Amount'), $hasPriceSets ? FALSE : TRUE, $attributes['total_amount'], TRUE, 'currency', NULL, $currencyFreeze); } $this->add('text', 'source', ts('Source'), CRM_Utils_Array::value('source', $attributes)); // CRM-7362 --add campaigns. CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values)); CRM_Contribute_Form_SoftCredit::buildQuickForm($this); $js = NULL; if (!$this->_mode) { $js = array('onclick' => "return verify( );"); } $mailingInfo = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME, 'mailing_backend'); $this->assign('outBound_option', $mailingInfo['outBound_option']); $this->addButtons(array(array('type' => 'upload', 'name' => ts('Save'), 'js' => $js, 'isDefault' => TRUE), array('type' => 'upload', 'name' => ts('Save and New'), 'js' => $js, 'subName' => 'new'), array('type' => 'cancel', 'name' => ts('Cancel')))); // if status is Cancelled freeze Amount, Payment Instrument, Check #, Financial Type, // Net and Fee Amounts are frozen in AdditionalInfo::buildAdditionalDetail if ($this->_id && $this->_values['contribution_status_id'] == array_search('Cancelled', $statusName)) { if ($totalAmount) { $totalAmount->freeze(); } $checkNumber->freeze(); $paymentInstrument->freeze(); $trxnId->freeze(); $financialType->freeze(); } // if contribution is related to membership or participant freeze Financial Type, Amount if ($this->_id && isset($this->_values['tax_amount'])) { $componentDetails = CRM_Contribute_BAO_Contribution::getComponentDetails($this->_id); if (CRM_Utils_Array::value('membership', $componentDetails) || CRM_Utils_Array::value('participant', $componentDetails)) { if ($totalAmount) { $totalAmount->freeze(); } $financialType->freeze(); $this->assign('freezeFinancialType', TRUE); } } if ($this->_action & CRM_Core_Action::VIEW) { $this->freeze(); } }
/** * Normalize/validate entity and action names * * @param string $entity * @param int $version * @return string * @throws \API_Exception */ public static function normalizeEntityName($entity, $version) { if ($version <= 3) { // APIv1-v3 munges entity/action names, and accepts any mixture of case and underscores. // We normalize entity to be CamelCase. return \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity)); } else { // APIv4 requires exact spelling & capitalization of entity/action name; deviations should cause errors if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $entity)) { throw new \API_Exception("Malformed entity"); } return $entity; } }
/** * Get camel case version of entity name. * * @param string|null $entity * * @return string|null */ function _civicrm_api_get_camel_name($entity) { return is_string($entity) ? CRM_Utils_String::convertStringToCamel($entity) : NULL; }
/** * Normalize entity to be CamelCase. * * APIv1-v3 munges entity/action names, and accepts any mixture of case and underscores. * * @param string $entity * @param int $version * @return string */ public static function normalizeEntityName($entity, $version) { return \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity)); }
/** * @param \Civi\API\Event\AuthorizeEvent $event * API authorization event. * @throws \API_Exception * @throws \Civi\API\Exception\UnauthorizedException */ public function onApiAuthorize(\Civi\API\Event\AuthorizeEvent $event) { $apiRequest = $event->getApiRequest(); if ($apiRequest['version'] == 3 && \CRM_Utils_String::convertStringToCamel($apiRequest['entity']) == $this->entityName && in_array(strtolower($apiRequest['action']), $this->actions)) { if (isset($apiRequest['params']['field_name'])) { $fldIdx = \CRM_Utils_Array::index(array('field_name'), $this->getCustomFields()); if (empty($fldIdx[$apiRequest['params']['field_name']])) { throw new \Exception("Failed to map custom field to entity table"); } $apiRequest['params']['entity_table'] = $fldIdx[$apiRequest['params']['field_name']]['entity_table']; unset($apiRequest['params']['field_name']); } if (empty($apiRequest['params']['id']) && empty($apiRequest['params']['entity_table'])) { throw new \API_Exception("Mandatory key(s) missing from params array: 'id' or 'entity_table'"); } if (isset($apiRequest['params']['id'])) { list($isValidId, $entityTable, $entityId) = $this->getDelegate($apiRequest['params']['id']); if ($isValidId && $entityTable && $entityId) { $this->authorizeDelegate($apiRequest['action'], $entityTable, $entityId, $apiRequest); $this->preventReassignment($apiRequest['params']['id'], $entityTable, $entityId, $apiRequest); return; } elseif ($isValidId) { throw new \API_Exception("Failed to match record to related entity"); } elseif (!$isValidId && strtolower($apiRequest['action']) == 'get') { // The matches will be an empty set; doesn't make a difference if we // reject or accept. // To pass SyntaxConformanceTest, we won't veto "get" on empty-set. return; } } if (isset($apiRequest['params']['entity_table'])) { $this->authorizeDelegate($apiRequest['action'], $apiRequest['params']['entity_table'], \CRM_Utils_Array::value('entity_id', $apiRequest['params'], NULL), $apiRequest); return; } throw new \API_Exception("Failed to run permission check"); } }
/** * Normalize/validate entity and action names * * @param string $entity * @param string $action * @param array $apiRequest * @throws \API_Exception */ protected static function normalizeNames(&$entity, &$action, &$apiRequest) { if ($apiRequest['version'] <= 3) { // APIv1-v3 munges entity/action names, and accepts any mixture of case and underscores. // We normalize entity to be CamelCase and action to be lowercase. $apiRequest['entity'] = $entity = \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity)); $apiRequest['action'] = $action = strtolower(\CRM_Utils_String::munge($action)); } else { // APIv4 requires exact spelling & capitalization of entity/action name; deviations should cause errors if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $entity)) { throw new \API_Exception("Malformed entity"); } if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $action)) { throw new \API_Exception("Malformed action"); } $apiRequest['entity'] = $entity; // TODO: Not sure about camelCase actions - in v3 they are all lowercase. $apiRequest['action'] = strtolower($action[0]) . substr($action, 1); } }