PageRenderTime 60ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/drupal/sites/all/modules/civicrm/api/v3/utils.php

https://github.com/michaelmcandrew/ste
PHP | 1862 lines | 1405 code | 168 blank | 289 comment | 346 complexity | 33cba0a06cabf17cb22d58a5ef7e30a0 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-1.0, LGPL-2.1
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 3.4 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2011 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the GNU Affero General Public License |
  12. | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the GNU Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the GNU Affero General Public |
  20. | License and the CiviCRM Licensing Exception along |
  21. | with this program; if not, contact CiviCRM LLC |
  22. | at info[AT]civicrm[DOT]org. If you have questions about the |
  23. | GNU Affero General Public License or the licensing of CiviCRM, |
  24. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  25. +--------------------------------------------------------------------+
  26. */
  27. /**
  28. * File for CiviCRM APIv3 utilitity functions
  29. *
  30. * @package CiviCRM_APIv3
  31. * @subpackage API_utils
  32. *
  33. * @copyright CiviCRM LLC (c) 2004-2011
  34. * @version $Id: utils.php 30879 2010-11-22 15:45:55Z shot $
  35. *
  36. */
  37. /**
  38. * Initialize CiviCRM - should be run at the start of each API function
  39. *
  40. * $useException boolean raise exception if set
  41. */
  42. function _civicrm_api3_initialize($useException = true )
  43. {
  44. require_once 'CRM/Core/Config.php';
  45. $config = CRM_Core_Config::singleton( );
  46. if ($useException) {
  47. CRM_Core_Error::setRaiseException();
  48. }
  49. }
  50. /*
  51. * Wrapper Function for civicrm_verify_mandatory to make it simple to pass either / or fields for checking
  52. *
  53. * @param array $params array of fields to check
  54. * @param array $daoName string DAO to check for required fields (create functions only)
  55. * @param array $keys list of required fields options. One of the options is required
  56. * @return null or throws error if there the required fields not present
  57. * @
  58. *
  59. */
  60. function civicrm_api3_verify_one_mandatory ($params, $daoName = null, $keyoptions = array() ) {
  61. foreach ($keyoptions as $key){
  62. $keys[0][] = $key;
  63. }
  64. civicrm_api3_verify_mandatory ($params, $daoName, $keys );
  65. }
  66. /*
  67. * Function to return the DAO of the function or Entity
  68. * @param $name is either a function of the api (civicrm_{entity}_create or the entity name
  69. * return the DAO name to manipulate this function
  70. * eg. "civicrm_api3_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
  71. */
  72. function _civicrm_api3_get_DAO ($name) {
  73. static $dao = null;
  74. if (!$dao) {
  75. require ('CRM/Core/DAO/.listAll.php');
  76. }
  77. if (strpos($name, 'civicrm_api3') !== false) {
  78. $last = strrpos ($name, '_') ;
  79. $name = substr ($name, 13, $last -13);// len ('civicrm_api3_') == 13
  80. if($name =='pledge_payment'){
  81. //for some reason pledge_payment doesn't follow normal conventions of BAO being the same as table name
  82. $name = 'Payment';
  83. }
  84. if($name =='custom_field'){
  85. //not handling camel case - there is a function in api.php that we could use?
  86. // for now adding example & putting in test for when we fix it
  87. $name = 'CustomField';
  88. }
  89. if($name =='custom_group'){
  90. $name = 'CustomGroup';
  91. }
  92. $name = ucfirst ($name);
  93. }
  94. return $dao[$name];
  95. }
  96. /*
  97. * Function to return the DAO of the function or Entity
  98. * @param $name is either a function of the api (civicrm_{entity}_create or the entity name
  99. * return the DAO name to manipulate this function
  100. * eg. "civicrm_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
  101. */
  102. function _civicrm_api3_get_BAO ($name) {
  103. $dao = _civicrm_api3_get_DAO($name);
  104. $dao = str_replace("DAO","BAO", $dao);
  105. return $dao;
  106. }
  107. /*
  108. * Function to check mandatory fields are included
  109. *
  110. * @param array $params array of fields to check
  111. * @param array $daoName string DAO to check for required fields (create functions only)
  112. * @param array $keys list of required fields. A value can be an array denoting that either this or that is required.
  113. * @param bool $verifyDAO
  114. * @return null or throws error if there the required fields not present
  115. */
  116. function civicrm_api3_verify_mandatory ($params, $daoName = null, $keys = array(), $verifyDAO = TRUE ) {
  117. if ( ! is_array( $params ) ) {
  118. throw new Exception ('Input variable `params` is not an array');
  119. }
  120. if ($daoName != null && $verifyDAO && !CRM_Utils_Array::value('id',$params)) {
  121. if(!is_array($unmatched =_civicrm_api3_check_required_fields( $params, $daoName, true))){
  122. $unmatched = array();
  123. }
  124. }
  125. require_once 'CRM/Utils/Array.php';
  126. if(CRM_Utils_Array::value('id',$params)){
  127. $keys = array('version');
  128. }else{
  129. $keys[] = 'version';//required from v3 onwards
  130. }
  131. foreach ($keys as $key) {
  132. if(is_array($key)){
  133. $match = 0;
  134. $optionset = array();
  135. foreach($key as $subkey){
  136. if ( !array_key_exists ($subkey, $params)|| empty($params[$subkey])) {
  137. $optionset[] = $subkey;
  138. }else{
  139. $match = 1;//as long as there is one match then we don't need to rtn anything
  140. }
  141. }
  142. if (empty($match) &&!empty($optionset)){
  143. $unmatched[] = "one of (". implode(", ",$optionset) . ")";
  144. }
  145. }else{
  146. if ( !array_key_exists ($key, $params) || empty($params[$key]))
  147. $unmatched[] = $key;
  148. }
  149. }
  150. if(!empty($unmatched)){
  151. throw new Exception("Mandatory key(s) missing from params array: " . implode(", ",$unmatched));
  152. }
  153. }
  154. /*
  155. * Verify if the params are of the right type
  156. * @param array $params array of params to check
  157. * @param string $type ('numeric' only for now)
  158. * @param string/object dao to test the param againsts (test the standard fields based on the schema definition)
  159. * @param array $extra contains arrays of (fieldname, type)
  160. * @return null or throws error if some of the params are not of the right type
  161. */
  162. function civicrm_api3_verify_type ($params, $dao, $extra) {
  163. throw new Exception("TODO: To be implemented");
  164. $notProperType = array();
  165. if ( !is_array( $keys ) ) {
  166. $keys = array ($keys) ;
  167. }
  168. foreach ($keys as $key) {
  169. if ( array_key_exists ($key, $params)) {
  170. switch ($type) {
  171. case 'numeric':
  172. if (!is_numeric($params[$key]))
  173. $notProperType[] = $key;
  174. break;
  175. default:
  176. throw new Exception("Type $type not known. Can't verify_type");
  177. }
  178. }
  179. }
  180. if(!empty($notProperType)){
  181. throw new Exception("Not of type $type " . implode(", ",$notProperType));
  182. }
  183. }
  184. /**
  185. *
  186. * @param <type> $msg
  187. * @param <type> $data
  188. * @param object $dao DAO / BAO object to be freed here
  189. * @return <type>
  190. */
  191. function &civicrm_api3_create_error( $msg, $data = null,&$dao = null )
  192. {
  193. if(is_object ($dao)){
  194. $dao->free();
  195. }
  196. return CRM_Core_Error::createAPIError( $msg, $data );
  197. }
  198. /**
  199. * Format array in result output styple
  200. * @param array $params
  201. * @dao object DAO object to be freed here
  202. * @return array $result
  203. */
  204. function civicrm_api3_create_success( $values = 1,$params=array(),&$dao = null )
  205. {
  206. $result = array();
  207. $result['is_error'] = 0;
  208. //if ( array_key_exists ('debug',$params) && is_object ($dao)) {
  209. if ( is_array($params) && array_key_exists ('debug',$params)) {
  210. if(!is_object ($dao)){
  211. $d = _civicrm_api3_get_DAO ($params['entity']);
  212. if (!empty($d)) {
  213. $file = str_replace ('_','/',$d).".php";
  214. require_once ($file);
  215. $dao = new $d();
  216. }
  217. }
  218. if(is_object ($dao)){
  219. $allFields = array_keys($dao->fields());
  220. $paramFields = array_keys($params);
  221. $undefined = array_diff ($paramFields, $allFields,array_keys($_COOKIE),array ('action','entity','debug','version','check_permissions','IDS_request_uri','IDS_user_agent','return','sequential'));
  222. if ($undefined)
  223. $result['undefined_fields'] = array_merge ($undefined);
  224. }
  225. }
  226. if(is_object ($dao)){
  227. $dao->free();
  228. }
  229. $result['version'] =3;
  230. if (is_array( $values)) {
  231. $result['count'] = count( $values);
  232. // Convert value-separated strings to array
  233. _civicrm_api3_separate_values( $values );
  234. if ( $result['count'] == 1 ) {
  235. list($result['id']) = array_keys($values);
  236. } elseif ( ! empty($values['id'] ) ) {
  237. $result['id']= $values['id'];
  238. }
  239. } else {
  240. $result['count'] = ! empty( $values ) ? 1 : 0;
  241. }
  242. if ( isset( $params['sequential'] ) &&
  243. $params['sequential'] ==1 ) {
  244. $result['values'] = array_merge($values);
  245. } else {
  246. $result['values'] = $values;
  247. }
  248. return $result;
  249. }
  250. /**
  251. * Recursive function to explode value-separated strings into arrays
  252. *
  253. */
  254. function _civicrm_api3_separate_values( &$values )
  255. {
  256. $sp = CRM_Core_DAO::VALUE_SEPARATOR;
  257. foreach ($values as &$value) {
  258. if (is_array($value)) {
  259. _civicrm_api3_separate_values($value);
  260. }
  261. elseif (is_string($value)) {
  262. if (strpos($value, $sp) !== FALSE) {
  263. $value = explode($sp, trim($value, $sp));
  264. }
  265. }
  266. }
  267. }
  268. /**
  269. * function to check if an error is actually a duplicate contact error
  270. *
  271. * @param array $error (array of) valid Error values
  272. *
  273. * @return true if error is duplicate contact error, false otherwise
  274. *
  275. * @access public
  276. */
  277. function civicrm_api3_duplicate($error)
  278. {
  279. if ( is_array( $error ) && civicrm_api3_error( $error ) ) {
  280. $code = $error['error_message']['code'];
  281. if ($code == CRM_Core_Error::DUPLICATE_CONTACT ) {
  282. return true ;
  283. }
  284. }
  285. return false;
  286. }
  287. /**
  288. * Check if the given array is actually an error
  289. *
  290. * @param array $params (reference ) input parameters
  291. *
  292. * @return boolean true if error, false otherwise
  293. * @static void
  294. * @access public
  295. */
  296. function civicrm_api3_error( $params )
  297. {
  298. if ( is_array( $params ) ) {
  299. return ( array_key_exists( 'is_error', $params ) &&
  300. $params['is_error'] ) ? true : false;
  301. }
  302. return false;
  303. }
  304. /**
  305. *
  306. * @param <type> $fields
  307. * @param <type> $params
  308. * @param <type> $values
  309. * @return <type>
  310. */
  311. function _civicrm_api3_store_values( &$fields, $params, &$values )
  312. {
  313. $valueFound = false;
  314. foreach ($fields as $name => $field) {
  315. // ignore all ids for now
  316. if ( $name === 'id' || substr( $name, -1, 3 ) === '_id' ) {
  317. continue;
  318. }
  319. if ( array_key_exists( $name, $params ) ) {
  320. $values[$name] = $params[$name];
  321. $valueFound = true;
  322. }
  323. }
  324. return $valueFound;
  325. }
  326. /*
  327. * Function transfers the filters being passed into the DAO onto the params object
  328. */
  329. function _civicrm_api3_dao_set_filter (&$dao,$params, $unique = TRUE ) {
  330. $entity = substr ($dao->__table , 8);
  331. if ( !$dao->find() ) {
  332. return array();
  333. }
  334. $fields = _civicrm_api3_build_fields_array($dao,$unique);
  335. $fields = array_intersect(array_keys($fields),array_keys($params));
  336. if( isset($params[$entity. "_id"])){
  337. //if entity_id is set then treat it as ID (will be overridden by id if set)
  338. $dao->id = $params[$entity. "_id"];
  339. }
  340. if (!$fields)
  341. return;
  342. foreach ($fields as $field) {
  343. $dao->$field = $params [$field];
  344. }
  345. }
  346. /*
  347. * build fields array. This is the array of fields as it relates to the given DAO
  348. * returns unique fields as keys by default but if set but can return by DB fields
  349. */
  350. function _civicrm_api3_build_fields_array(&$dao, $unique = TRUE){
  351. $fields = $dao->fields();
  352. if ($unique){
  353. return $fields;
  354. }
  355. foreach($fields as $field){
  356. $dbFields[$field['name']] = $field;
  357. }
  358. return $dbFields;
  359. }
  360. /**
  361. * Converts an DAO object to an array
  362. *
  363. * @param object $dao (reference )object to convert
  364. * @params array of arrays (key = id) of array of fields
  365. * @static void
  366. * @access public
  367. */
  368. function _civicrm_api3_dao_to_array ($dao, $params = null,$uniqueFields = TRUE) {
  369. $result = array();
  370. if ( !$dao->find() ) {
  371. return array();
  372. }
  373. $fields = array_keys(_civicrm_api3_build_fields_array($dao, $uniqueFields));
  374. while ( $dao->fetch() ) {
  375. $tmp = array();
  376. foreach( $fields as $key ) {
  377. if (array_key_exists($key, $dao)) {
  378. // not sure on that one
  379. if ($dao->$key !== null)
  380. $tmp[$key] = $dao->$key;
  381. }
  382. }
  383. $result[$dao->id] = $tmp;
  384. }
  385. return $result;
  386. }
  387. /**
  388. * Converts an object to an array
  389. *
  390. * @param object $dao (reference )object to convert
  391. * @param array $dao (reference )array
  392. * @param array $uniqueFields
  393. * @return array
  394. * @static void
  395. * @access public
  396. */
  397. function _civicrm_api3_object_to_array( &$dao, &$values,$uniqueFields = FALSE )
  398. {
  399. $fields = _civicrm_api3_build_fields_array($dao,$uniqueFields);
  400. foreach( $fields as $key => $value ) {
  401. if (array_key_exists($key, $dao)) {
  402. $values[$key] = $dao->$key;
  403. }
  404. }
  405. }
  406. /*
  407. * Wrapper for _civicrm_object_to_array when api supports unique fields
  408. */
  409. function _civicrm_api3_object_to_array_unique_fields( &$dao, &$values ) {
  410. return _civicrm_api3_object_to_array( $dao, $values, TRUE );
  411. }
  412. /*
  413. * Function to get existing values when an 'id' is passed into a Create api
  414. *
  415. * @params array $params input params
  416. * @return array $valuse params with existing values from contact
  417. */
  418. function civicrm_api3_update_get_existing($params, $function){
  419. $function = str_replace ( 'create' , 'get', $function );
  420. $values = $params;
  421. if(!empty($params['id'])){
  422. $getparams = array('id' => $params['id'],'version' => 3);
  423. $result = $function($getparams);
  424. $values = array_merge($result['values'][$params['id']],$params);
  425. }
  426. return $values;
  427. }
  428. /**
  429. * This function adds the contact variable in $values to the
  430. * parameter list $params. For most cases, $values should have length 1. If
  431. * the variable being added is a child of Location, a location_type_id must
  432. * also be included. If it is a child of phone, a phone_type must be included.
  433. *
  434. * @param array $values The variable(s) to be added
  435. * @param array $params The structured parameter list
  436. *
  437. * @return bool|CRM_Utils_Error
  438. * @access public
  439. */
  440. function _civicrm_api3_add_formatted_param(&$values, $params)
  441. {
  442. /* Crawl through the possible classes:
  443. * Contact
  444. * Individual
  445. * Household
  446. * Organization
  447. * Location
  448. * Address
  449. * Email
  450. * Phone
  451. * IM
  452. * Note
  453. * Custom
  454. */
  455. /* Cache the various object fields */
  456. static $fields = null;
  457. if ($fields == null) {
  458. $fields = array();
  459. }
  460. //first add core contact values since for other Civi modules they are not added
  461. require_once 'CRM/Contact/BAO/Contact.php';
  462. $contactFields =& CRM_Contact_DAO_Contact::fields( );
  463. _civicrm_api3_store_values( $contactFields, $values, $params );
  464. if (isset($values['contact_type'])) {
  465. /* we're an individual/household/org property */
  466. $fields[$values['contact_type']] = CRM_Contact_DAO_Contact::fields();
  467. _civicrm_api3_store_values( $fields[$values['contact_type']], $values, $params );
  468. return true;
  469. }
  470. if ( isset($values['individual_prefix']) ) {
  471. if ( $params['prefix_id'] ) {
  472. $prefixes = array( );
  473. $prefixes = CRM_Core_PseudoConstant::individualPrefix( );
  474. $params['prefix'] = $prefixes[$params['prefix_id']];
  475. } else {
  476. $params['prefix'] = $values['individual_prefix'];
  477. }
  478. return true;
  479. }
  480. if (isset($values['individual_suffix'])) {
  481. if ( $params['suffix_id'] ) {
  482. $suffixes = array( );
  483. $suffixes = CRM_Core_PseudoConstant::individualSuffix( );
  484. $params['suffix'] = $suffixes[$params['suffix_id']];
  485. } else {
  486. $params['suffix'] = $values['individual_suffix'];
  487. }
  488. return true;
  489. }
  490. //CRM-4575
  491. if ( isset( $values['email_greeting'] ) ) {
  492. if ( $params['email_greeting_id'] ) {
  493. $emailGreetings = array( );
  494. $emailGreetingFilter = array( 'contact_type' => CRM_Utils_Array::value('contact_type', $params),
  495. 'greeting_type' => 'email_greeting' );
  496. $emailGreetings = CRM_Core_PseudoConstant::greeting( $emailGreetingFilter );
  497. $params['email_greeting'] = $emailGreetings[$params['email_greeting_id']];
  498. } else {
  499. $params['email_greeting'] = $values['email_greeting'];
  500. }
  501. return true;
  502. }
  503. if ( isset($values['postal_greeting'] ) ) {
  504. if ( $params['postal_greeting_id'] ) {
  505. $postalGreetings = array( );
  506. $postalGreetingFilter = array( 'contact_type' => CRM_Utils_Array::value('contact_type', $params),
  507. 'greeting_type' => 'postal_greeting' );
  508. $postalGreetings = CRM_Core_PseudoConstant::greeting( $postalGreetingFilter );
  509. $params['postal_greeting'] = $postalGreetings[$params['postal_greeting_id']];
  510. } else {
  511. $params['postal_greeting'] = $values['postal_greeting'];
  512. }
  513. return true;
  514. }
  515. if ( isset($values['addressee'] ) ) {
  516. if ( $params['addressee_id'] ) {
  517. $addressee = array( );
  518. $addresseeFilter = array( 'contact_type' => CRM_Utils_Array::value('contact_type', $params),
  519. 'greeting_type' => 'addressee' );
  520. $addressee = CRM_Core_PseudoConstant::addressee( $addresseeFilter );
  521. $params['addressee'] = $addressee[$params['addressee_id']];
  522. } else {
  523. $params['addressee'] = $values['addressee'];
  524. }
  525. return true;
  526. }
  527. if ( isset($values['gender']) ) {
  528. if ( $params['gender_id'] ) {
  529. $genders = array( );
  530. $genders = CRM_Core_PseudoConstant::gender( );
  531. $params['gender'] = $genders[$params['gender_id']];
  532. } else {
  533. $params['gender'] = $values['gender'];
  534. }
  535. return true;
  536. }
  537. if ( isset($values['preferred_communication_method']) ) {
  538. $comm = array( );
  539. $preffComm = array( );
  540. $pcm = array( );
  541. $pcm = array_change_key_case( array_flip( CRM_Core_PseudoConstant::pcm() ), CASE_LOWER);
  542. $preffComm = explode(',' , $values['preferred_communication_method']);
  543. foreach ($preffComm as $v) {
  544. $v = strtolower(trim($v));
  545. if ( array_key_exists ( $v, $pcm) ) {
  546. $comm[$pcm[$v]] = 1;
  547. }
  548. }
  549. $params['preferred_communication_method'] = $comm;
  550. return true;
  551. }
  552. //format the website params.
  553. if ( CRM_Utils_Array::value( 'url', $values ) ) {
  554. static $websiteFields;
  555. if ( !is_array( $websiteFields ) ) {
  556. require_once 'CRM/Core/DAO/Website.php';
  557. $websiteFields = CRM_Core_DAO_Website::fields( );
  558. }
  559. if ( !array_key_exists( 'website', $params ) ||
  560. !is_array( $params['website'] ) ) {
  561. $params['website'] = array( );
  562. }
  563. $websiteCount = count( $params['website'] );
  564. _civicrm_api3_store_values( $websiteFields, $values,
  565. $params['website'][++$websiteCount] );
  566. return true;
  567. }
  568. // get the formatted location blocks into params - w/ 3.0 format, CRM-4605
  569. if ( CRM_Utils_Array::value( 'location_type_id', $values ) ) {
  570. _civicrm_api3_add_formatted_location_blocks( $values, $params );
  571. return true;
  572. }
  573. if (isset($values['note'])) {
  574. /* add a note field */
  575. if (!isset($params['note'])) {
  576. $params['note'] = array();
  577. }
  578. $noteBlock = count($params['note']) + 1;
  579. $params['note'][$noteBlock] = array();
  580. if (!isset($fields['Note'])) {
  581. $fields['Note'] = CRM_Core_DAO_Note::fields();
  582. }
  583. // get the current logged in civicrm user
  584. $session = CRM_Core_Session::singleton( );
  585. $userID = $session->get( 'userID' );
  586. if ( $userID ) {
  587. $values['contact_id'] = $userID;
  588. }
  589. _civicrm_api3_store_values($fields['Note'], $values, $params['note'][$noteBlock]);
  590. return true;
  591. }
  592. /* Check for custom field values */
  593. if ($fields['custom'] == null) {
  594. $fields['custom'] =& CRM_Core_BAO_CustomField::getFields( $values['contact_type'], false, false, null, null, false, false, false );
  595. }
  596. foreach ($values as $key => $value) {
  597. if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
  598. /* check if it's a valid custom field id */
  599. if (!array_key_exists($customFieldID, $fields['custom'])) {
  600. return civicrm_api3_create_error('Invalid custom field ID');
  601. } else {
  602. $params[$key] = $value;
  603. }
  604. }
  605. }
  606. }
  607. /**
  608. * This function format location blocks w/ v3.0 format.
  609. *
  610. * @param array $values The variable(s) to be added
  611. * @param array $params The structured parameter list
  612. *
  613. * @return bool
  614. * @access public
  615. */
  616. function _civicrm_api3_add_formatted_location_blocks( &$values, $params )
  617. {
  618. static $fields = null;
  619. if ( $fields == null ) {
  620. $fields = array();
  621. }
  622. foreach ( array( 'Phone', 'Email', 'IM', 'OpenID' ) as $block ) {
  623. $name = strtolower( $block );
  624. if ( !array_key_exists( $name, $values ) ) continue;
  625. // block present in value array.
  626. if ( !array_key_exists($name, $params) || !is_array($params[$name]) ) $params[$name] = array( );
  627. if ( !array_key_exists( $block, $fields ) ) {
  628. require_once( str_replace('_', DIRECTORY_SEPARATOR, "CRM_Core_DAO_" . $block ) . ".php");
  629. eval( '$fields[$block] =& CRM_Core_DAO_' . $block . '::fields( );' );
  630. }
  631. $blockCnt = count( $params[$name] );
  632. // copy value to dao field name.
  633. if ( $name == 'im' ) $values['name'] = $values[$name];
  634. _civicrm_api3_store_values( $fields[$block ], $values,
  635. $params[$name][++$blockCnt] );
  636. if ( !CRM_Utils_Array::value( 'id', $params ) && ( $blockCnt == 1 ) ) {
  637. $params[$name][$blockCnt]['is_primary'] = true;
  638. }
  639. // we only process single block at a time.
  640. return true;
  641. }
  642. // handle address fields.
  643. if ( !array_key_exists('address', $params) || !is_array($params['address']) ) $params['address'] = array( );
  644. $addressCnt = 1;
  645. foreach ( $params['address'] as $cnt => $addressBlock ) {
  646. if ( CRM_Utils_Array::value( 'location_type_id', $values ) ==
  647. CRM_Utils_Array::value( 'location_type_id', $addressBlock ) ) {
  648. $addressCnt = $cnt;
  649. break;
  650. }
  651. $addressCnt++;
  652. }
  653. if ( !array_key_exists( 'Address', $fields ) ) {
  654. require_once 'CRM/Core/DAO/Address.php';
  655. $fields['Address'] =& CRM_Core_DAO_Address::fields( );
  656. }
  657. _civicrm_api3_store_values( $fields['Address'], $values, $params['address'][$addressCnt] );
  658. $addressFields = array( 'county', 'country', 'state_province',
  659. 'supplemental_address_1', 'supplemental_address_2',
  660. 'StateProvince.name' );
  661. foreach ( $addressFields as $field ) {
  662. if ( array_key_exists( $field, $values ) ) {
  663. if ( !array_key_exists( 'address', $params ) ) $params['address'] = array( );
  664. $params['address'][$addressCnt][$field] = $values[$field];
  665. }
  666. }
  667. if ( $addressCnt == 1 ) $params['address'][$addressCnt]['is_primary'] = true;
  668. return true;
  669. }
  670. /**
  671. * Check a formatted parameter list for required fields. Note that this
  672. * function does no validation or dupe checking.
  673. *
  674. * @param array $params Structured parameter list (as in crm_format_params)
  675. *
  676. * @return bool|CRM_core_Error Parameter list has all required fields
  677. * @access public
  678. */
  679. function _civicrm_api3_required_formatted_contact($params)
  680. {
  681. if (! isset($params['contact_type'])) {
  682. return civicrm_api3_create_error('No contact type specified');
  683. }
  684. switch ($params['contact_type']) {
  685. case 'Individual':
  686. if (isset($params['first_name']) && isset($params['last_name'])) {
  687. return civicrm_api3_create_success(true);
  688. }
  689. if ( array_key_exists( 'email', $params ) &&
  690. is_array( $params['email'] ) &&
  691. !CRM_Utils_System::isNull( $params['email'] ) ) {
  692. return civicrm_api3_create_success(true);
  693. }
  694. break;
  695. case 'Household':
  696. if (isset($params['household_name'])) {
  697. return civicrm_api3_create_success(true);
  698. }
  699. break;
  700. case 'Organization':
  701. if (isset($params['organization_name'])) {
  702. return civicrm_api3_create_success(true);
  703. }
  704. break;
  705. default:
  706. return
  707. civicrm_api3_create_error('Invalid Contact Type: ' . $params['contact_type'] );
  708. }
  709. return civicrm_api3_create_error('Missing required fields');
  710. }
  711. /**
  712. *
  713. * @param <type> $params
  714. * @return <type>
  715. */
  716. function _civicrm_api3_duplicate_formatted_contact($params)
  717. {
  718. $id = CRM_Utils_Array::value( 'id', $params );
  719. $externalId = CRM_Utils_Array::value( 'external_identifier', $params );
  720. if ( $id || $externalId ) {
  721. $contact = new CRM_Contact_DAO_Contact( );
  722. $contact->id = $id;
  723. $contact->external_identifier = $externalId;
  724. if ( $contact->find( true ) ) {
  725. if ( $params['contact_type'] != $contact->contact_type ) {
  726. return civicrm_api3_create_error( "Mismatched contact IDs OR Mismatched contact Types" );
  727. }
  728. $error = CRM_Core_Error::createError( "Found matching contacts: $contact->id",
  729. CRM_Core_Error::DUPLICATE_CONTACT,
  730. 'Fatal', $contact->id );
  731. return civicrm_api3_create_error( $error->pop( ) );
  732. }
  733. } else {
  734. require_once 'CRM/Dedupe/Finder.php';
  735. $dedupeParams = CRM_Dedupe_Finder::formatParams($params, $params['contact_type']);
  736. $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['contact_type'], 'Strict');
  737. if ( !empty($ids) ) {
  738. $ids = implode( ',', $ids );
  739. $error = CRM_Core_Error::createError( "Found matching contacts: $ids",
  740. CRM_Core_Error::DUPLICATE_CONTACT,
  741. 'Fatal', $ids );
  742. return civicrm_api3_create_error( $error->pop( ) );
  743. }
  744. }
  745. return civicrm_api3_create_success( true );
  746. }
  747. /**
  748. * Validate a formatted contact parameter list.
  749. *
  750. * @param array $params Structured parameter list (as in crm_format_params)
  751. *
  752. * @return bool|CRM_Core_Error
  753. * @access public
  754. */
  755. function _civicrm_api3_validate_formatted_contact($params)
  756. {
  757. /* Look for offending email addresses */
  758. if ( array_key_exists( 'email', $params ) ) {
  759. foreach ( $params['email'] as $count => $values ) {
  760. if( !is_array( $values ) ) continue;
  761. if ( $email = CRM_Utils_Array::value( 'email', $values ) ) {
  762. //validate each email
  763. if ( !CRM_Utils_Rule::email( $email ) ) {
  764. return civicrm_api3_create_error( 'No valid email address');
  765. }
  766. //check for loc type id.
  767. if ( !CRM_Utils_Array::value( 'location_type_id', $values ) ) {
  768. return civicrm_api3_create_error( 'Location Type Id missing.');
  769. }
  770. }
  771. }
  772. }
  773. /* Validate custom data fields */
  774. if ( array_key_exists( 'custom', $params ) && is_array($params['custom']) ) {
  775. foreach ($params['custom'] as $key => $custom) {
  776. if (is_array($custom)) {
  777. $valid = CRM_Core_BAO_CustomValue::typecheck(
  778. $custom['type'], $custom['value']);
  779. if (! $valid) {
  780. return civicrm_api3_create_error('Invalid value for custom field \'' .
  781. $custom['name']. '\'');
  782. }
  783. if ( $custom['type'] == 'Date' ) {
  784. $params['custom'][$key]['value'] = str_replace( '-', '', $params['custom'][$key]['value'] );
  785. }
  786. }
  787. }
  788. }
  789. return civicrm_api3_create_success( true );
  790. }
  791. /**
  792. *
  793. * @param array $params
  794. * @param array $values
  795. * @param string $extends entity that this custom field extends (e.g. contribution, event, contact)
  796. * @param string $entityId ID of entity per $extends
  797. */
  798. function _civicrm_api3_custom_format_params( $params, &$values, $extends, $entityId = null )
  799. {
  800. $values['custom'] = array();
  801. require_once 'CRM/Core/BAO/CustomField.php';
  802. foreach ($params as $key => $value) {
  803. list( $customFieldID, $customValueID ) = CRM_Core_BAO_CustomField::getKeyID($key, true );
  804. if ( $customFieldID ) {
  805. CRM_Core_BAO_CustomField::formatCustomField( $customFieldID, $values['custom'],
  806. $value, $extends, $customValueID, $entityId, false, false );
  807. }
  808. }
  809. }
  810. /**
  811. * This function ensures that we have the right input parameters
  812. *
  813. * We also need to make sure we run all the form rules on the params list
  814. * to ensure that the params are valid
  815. *
  816. * @param array $params Associative array of property name/value
  817. * pairs to insert in new history.
  818. * @daoName string DAO to check params agains
  819. * @return bool should the missing fields be returned as an array (core error created as default)
  820. *
  821. * @todo the check for required fields unsets the ID as that isn't required for create but potentially also unsets other ID fields, note also the DAO might be a bit 'harsh' in it's required fields as the BAO handles some
  822. * @return bool true if all fields present, depending on $result a core error is created of an array of missing fields is returned
  823. * @access public
  824. */
  825. function _civicrm_api3_check_required_fields( $params, $daoName, $return = FALSE)
  826. {
  827. if ( isset($params['extends'] ) ) {
  828. if ( ( $params['extends'] == 'Activity' ||
  829. $params['extends'] == 'Phonecall' ||
  830. $params['extends'] == 'Meeting' ||
  831. $params['extends'] == 'Group' ||
  832. $params['extends'] == 'Contribution'
  833. ) &&
  834. ( $params['style'] == 'Tab' ) ) {
  835. return civicrm_api3_create_error(ts("Can not create Custom Group in Tab for ". $params['extends']));
  836. }
  837. }
  838. require_once(str_replace('_', DIRECTORY_SEPARATOR, $daoName) . ".php");
  839. $dao = new $daoName();
  840. $fields = $dao->fields();
  841. $missing = array();
  842. foreach ($fields as $k => $v) {
  843. if ($v['name'] == 'id') {
  844. continue;
  845. }
  846. if ( CRM_Utils_Array::value( 'required', $v ) ) {
  847. if ( empty( $params[$k] ) && !( $params[$k] === 0 ) ) { // 0 is a valid input for numbers, CRM-8122
  848. $missing[] = $k;
  849. }
  850. }
  851. }
  852. if (!empty($missing)) {
  853. if (!empty($return)) {
  854. return $missing;
  855. }else{
  856. return civicrm_api3_create_error(ts("Required fields ". implode(',', $missing) . " for $daoName are not present"));
  857. }
  858. }
  859. return true;
  860. }
  861. /**
  862. * take the input parameter list as specified in the data model and
  863. * convert it into the same format that we use in QF and BAO object
  864. *
  865. * @param array $params Associative array of property name/value
  866. * pairs to insert in new contact.
  867. * @param array $values The reformatted properties that we can use internally
  868. *
  869. * @param array $create Is the formatted Values array going to
  870. * be used for CRM_Event_BAO_Participant:create()
  871. *
  872. * @return array|CRM_Error
  873. * @access public
  874. */
  875. function _civicrm_api3_participant_formatted_param( $params, &$values, $create=false)
  876. {
  877. $fields =& CRM_Event_DAO_Participant::fields( );
  878. _civicrm_api3_store_values( $fields, $params, $values );
  879. require_once 'CRM/Core/OptionGroup.php';
  880. $customFields = CRM_Core_BAO_CustomField::getFields( 'Participant', false, false, null, null, false, false, false );
  881. foreach ($params as $key => $value) {
  882. // ignore empty values or empty arrays etc
  883. if ( CRM_Utils_System::isNull( $value ) ) {
  884. continue;
  885. }
  886. //Handling Custom Data
  887. if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
  888. $values[$key] = $value;
  889. $type = $customFields[$customFieldID]['html_type'];
  890. if( $type == 'CheckBox' || $type == 'Multi-Select' ) {
  891. $mulValues = explode( ',' , $value );
  892. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  893. $values[$key] = array();
  894. foreach( $mulValues as $v1 ) {
  895. foreach($customOption as $customValueID => $customLabel) {
  896. $customValue = $customLabel['value'];
  897. if (( strtolower(trim($customLabel['label'])) == strtolower(trim($v1)) ) ||
  898. ( strtolower(trim($customValue)) == strtolower(trim($v1)) )) {
  899. if ( $type == 'CheckBox' ) {
  900. $values[$key][$customValue] = 1;
  901. } else {
  902. $values[$key][] = $customValue;
  903. }
  904. }
  905. }
  906. }
  907. } else if ( $type == 'Select' || $type == 'Radio' ) {
  908. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  909. foreach( $customOption as $customFldID => $customValue ) {
  910. $val = CRM_Utils_Array::value( 'value', $customValue );
  911. $label = CRM_Utils_Array::value( 'label', $customValue );
  912. $label = strtolower( $label );
  913. $value = strtolower( trim( $value ) );
  914. if ( ( $value == $label ) || ( $value == strtolower( $val ) ) ) {
  915. $values[$key] = $val;
  916. }
  917. }
  918. }
  919. }
  920. switch ($key) {
  921. case 'participant_contact_id':
  922. if (!CRM_Utils_Rule::integer($value)) {
  923. return civicrm_api3_create_error("contact_id not valid: $value");
  924. }
  925. $dao = new CRM_Core_DAO();
  926. $qParams = array();
  927. $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
  928. $qParams);
  929. if (!$svq) {
  930. return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value.");
  931. }
  932. $values['contact_id'] = $values['participant_contact_id'];
  933. unset ($values['participant_contact_id']);
  934. break;
  935. case 'participant_register_date':
  936. if (!CRM_Utils_Rule::date($value)) {
  937. return civicrm_api3_create_error("$key not a valid date: $value");
  938. }
  939. break;
  940. case 'event_title':
  941. $id = CRM_Core_DAO::getFieldValue( "CRM_Event_DAO_Event", $value, 'id', 'title' );
  942. $values['event_id'] = $id;
  943. break;
  944. case 'event_id':
  945. if (!CRM_Utils_Rule::integer($value)) {
  946. return civicrm_api3_create_error("Event ID is not valid: $value");
  947. }
  948. $dao = new CRM_Core_DAO();
  949. $qParams = array();
  950. $svq = $dao->singleValueQuery("SELECT id FROM civicrm_event WHERE id = $value",
  951. $qParams);
  952. if (!$svq) {
  953. return civicrm_api3_create_error("Invalid Event ID: There is no event record with event_id = $value.");
  954. }
  955. break;
  956. case 'participant_status_id':
  957. $id = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_ParticipantStatusType', $value, 'id', 'label');
  958. $values[$key] = $id;
  959. break;
  960. case 'participant_role_id':
  961. case 'participant_role':
  962. $role = CRM_Event_PseudoConstant::participantRole();
  963. $participantRoles = explode( ",", $value );
  964. foreach ( $participantRoles as $k => $v ) {
  965. $v = trim( $v );
  966. if ( $key == 'participant_role' ) {
  967. $participantRoles[$k] = CRM_Utils_Array::key( $v, $role );
  968. } else {
  969. $participantRoles[$k] = $v;
  970. }
  971. }
  972. require_once 'CRM/Core/DAO.php';
  973. $values['role_id'] = implode( CRM_Core_DAO::VALUE_SEPARATOR, $participantRoles );
  974. unset( $values[$key] );
  975. break;
  976. default:
  977. break;
  978. }
  979. }
  980. if ( array_key_exists( 'participant_note', $params ) ) {
  981. $values['participant_note'] = $params['participant_note'];
  982. }
  983. if ( $create ) {
  984. // CRM_Event_BAO_Participant::create() handles register_date,
  985. // status_id and source. So, if $values contains
  986. // participant_register_date, participant_status_id or participant_source,
  987. // convert it to register_date, status_id or source
  988. $changes = array('participant_register_date' => 'register_date',
  989. 'participant_source' => 'source',
  990. 'participant_status_id' => 'status_id',
  991. 'participant_role_id' => 'role_id',
  992. 'participant_fee_level' => 'fee_level',
  993. 'participant_fee_amount' => 'fee_amount',
  994. 'participant_id' => 'id'
  995. );
  996. foreach ($changes as $orgVal => $changeVal) {
  997. if ( isset($values[$orgVal]) ) {
  998. $values[$changeVal] = $values[$orgVal];
  999. unset($values[$orgVal]);
  1000. }
  1001. }
  1002. }
  1003. return null;
  1004. }
  1005. /**
  1006. * take the input parameter list as specified in the data model and
  1007. * convert it into the same format that we use in QF and BAO object
  1008. *
  1009. * @param array $params Associative array of property name/value
  1010. * pairs to insert in new contact.
  1011. * @param array $values The reformatted properties that we can use internally
  1012. * '
  1013. * @return array|CRM_Error
  1014. * @access public
  1015. */
  1016. function _civicrm_api3_contribute_formatted_param( $params, &$values, $create=false )
  1017. {
  1018. // copy all the contribution fields as is
  1019. $fields =& CRM_Contribute_DAO_Contribution::fields( );
  1020. _civicrm_api3_store_values( $fields, $params, $values );
  1021. require_once 'CRM/Core/OptionGroup.php';
  1022. $customFields = CRM_Core_BAO_CustomField::getFields( 'Contribution', false, false, null, null, false, false, false );
  1023. foreach ($params as $key => $value) {
  1024. // ignore empty values or empty arrays etc
  1025. if ( CRM_Utils_System::isNull( $value ) ) {
  1026. continue;
  1027. }
  1028. //Handling Custom Data
  1029. if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
  1030. $values[$key] = $value;
  1031. $type = $customFields[$customFieldID]['html_type'];
  1032. if( $type == 'CheckBox' || $type == 'Multi-Select' ) {
  1033. $mulValues = explode( ',' , $value );
  1034. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1035. $values[$key] = array();
  1036. foreach( $mulValues as $v1 ) {
  1037. foreach($customOption as $customValueID => $customLabel) {
  1038. $customValue = $customLabel['value'];
  1039. if (( strtolower($customLabel['label']) == strtolower(trim($v1)) ) ||
  1040. ( strtolower($customValue) == strtolower(trim($v1)) )) {
  1041. if ( $type == 'CheckBox' ) {
  1042. $values[$key][$customValue] = 1;
  1043. } else {
  1044. $values[$key][] = $customValue;
  1045. }
  1046. }
  1047. }
  1048. }
  1049. } else if ( $type == 'Select' || $type == 'Radio' ||
  1050. ( $type == 'Autocomplete-Select' &&
  1051. $customFields[$customFieldID]['data_type'] == 'String' ) ) {
  1052. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1053. foreach( $customOption as $customFldID => $customValue ) {
  1054. $val = CRM_Utils_Array::value( 'value', $customValue );
  1055. $label = CRM_Utils_Array::value( 'label', $customValue );
  1056. $label = strtolower( $label );
  1057. $value = strtolower( trim( $value ) );
  1058. if ( ( $value == $label ) || ( $value == strtolower( $val ) ) ) {
  1059. $values[$key] = $val;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. switch ($key) {
  1065. case 'contribution_contact_id':
  1066. if (!CRM_Utils_Rule::integer($value)) {
  1067. return civicrm_api3_create_error("contact_id not valid: $value");
  1068. }
  1069. $dao = new CRM_Core_DAO();
  1070. $qParams = array();
  1071. $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
  1072. $qParams);
  1073. if (!$svq) {
  1074. return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value.");
  1075. }
  1076. $values['contact_id'] = $values['contribution_contact_id'];
  1077. unset ($values['contribution_contact_id']);
  1078. break;
  1079. case 'contact_type':
  1080. //import contribution record according to select contact type
  1081. require_once 'CRM/Contact/DAO/Contact.php';
  1082. $contactType = new CRM_Contact_DAO_Contact();
  1083. //when insert mode check contact id or external identifire
  1084. if ( $params['contribution_contact_id'] || $params['external_identifier'] ) {
  1085. if ( $params['contribution_contact_id'] ) {
  1086. $contactType->id = $params['contribution_contact_id'];
  1087. } else if( $params['external_identifier'] ) {
  1088. $contactType->external_identifier = $params['external_identifier'];
  1089. }
  1090. if ( $contactType->find(true) ) {
  1091. if ( $params['contact_type'] != $contactType->contact_type ) {
  1092. return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type");
  1093. }
  1094. }
  1095. } else if ( $params['contribution_id'] || $params['trxn_id'] ||$params['invoice_id'] ) {
  1096. //when update mode check contribution id or trxn id or
  1097. //invoice id
  1098. $contactId = new CRM_Contribute_DAO_Contribution();
  1099. if ( $params['contribution_id'] ) {
  1100. $contactId->id = $params['contribution_id'];
  1101. } else if ( $params['trxn_id'] ) {
  1102. $contactId->trxn_id = $params['trxn_id'];
  1103. } else if ( $params['invoice_id'] ) {
  1104. $contactId->invoice_id = $params['invoice_id'];
  1105. }
  1106. if ( $contactId->find(true) ) {
  1107. $contactType->id = $contactId->contact_id;
  1108. if ( $contactType->find(true) ) {
  1109. if ( $params['contact_type'] != $contactType->contact_type ) {
  1110. return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type");
  1111. }
  1112. }
  1113. }
  1114. }
  1115. break;
  1116. case 'receive_date':
  1117. case 'cancel_date':
  1118. case 'receipt_date':
  1119. case 'thankyou_date':
  1120. if (!CRM_Utils_Rule::date($value)) {
  1121. return civicrm_api3_create_error("$key not a valid date: $value");
  1122. }
  1123. break;
  1124. case 'non_deductible_amount':
  1125. case 'total_amount':
  1126. case 'fee_amount':
  1127. case 'net_amount':
  1128. if (!CRM_Utils_Rule::money($value)) {
  1129. return civicrm_api3_create_error("$key not a valid amount: $value");
  1130. }
  1131. break;
  1132. case 'currency':
  1133. if (!CRM_Utils_Rule::currencyCode($value)) {
  1134. return civicrm_api3_create_error("currency not a valid code: $value");
  1135. }
  1136. break;
  1137. case 'contribution_type':
  1138. require_once 'CRM/Contribute/PseudoConstant.php';
  1139. $contriTypes = CRM_Contribute_PseudoConstant::contributionType( );
  1140. foreach ( $contriTypes as $val => $type ) {
  1141. if ( strtolower( $value ) == strtolower( $type ) ) {
  1142. $values['contribution_type_id'] = $val;
  1143. break;
  1144. }
  1145. }
  1146. if ( !CRM_Utils_Array::value( 'contribution_type_id', $values ) ) {
  1147. return civicrm_api3_create_error("Contribution Type is not valid: $value");
  1148. }
  1149. break;
  1150. case 'payment_instrument':
  1151. require_once 'CRM/Core/OptionGroup.php';
  1152. $values['payment_instrument_id'] = CRM_Core_OptionGroup::getValue( 'payment_instrument', $value );
  1153. if ( !CRM_Utils_Array::value( 'payment_instrument_id', $values ) ) {
  1154. return civicrm_api3_create_error("Payment Instrument is not valid: $value");
  1155. }
  1156. break;
  1157. case 'contribution_status_id':
  1158. require_once 'CRM/Core/OptionGroup.php';
  1159. if ( !$values['contribution_status_id'] = CRM_Core_OptionGroup::getValue( 'contribution_status', $value )) {
  1160. return civicrm_api3_create_error("Contribution Status is not valid: $value");
  1161. }
  1162. break;
  1163. case 'honor_type_id':
  1164. require_once 'CRM/Core/OptionGroup.php';
  1165. $values['honor_type_id'] = CRM_Core_OptionGroup::getValue( 'honor_type', $value );
  1166. if ( !CRM_Utils_Array::value( 'honor_type_id', $values ) ) {
  1167. return civicrm_api3_create_error("Honor Type is not valid: $value");
  1168. }
  1169. break;
  1170. case 'soft_credit':
  1171. //import contribution record according to select contact type
  1172. // validate contact id and external identifier.
  1173. $contactId = CRM_Utils_Array::value( 'contact_id', $params['soft_credit'] );
  1174. $externalId = CRM_Utils_Array::value( 'external_identifier', $params['soft_credit'] );
  1175. if ( $contactId || $externalId ) {
  1176. require_once 'CRM/Contact/DAO/Contact.php';
  1177. $contact = new CRM_Contact_DAO_Contact();
  1178. $contact->id = $contactId;
  1179. $contact->external_identifier = $externalId;
  1180. $errorMsg = null;
  1181. if ( !$contact->find( true ) ) {
  1182. $errorMsg = ts( "No match found for specified Soft Credit contact data. Row was skipped." );
  1183. } else if ( $params['contact_type'] != $contact->contact_type ) {
  1184. $errorMsg = ts( "Soft Credit Contact Type is wrong: %1", array( 1 => $contact->contact_type ) );
  1185. }
  1186. if ( $errorMsg ) {
  1187. return civicrm_api3_create_error( $errorMsg, 'soft_credit' );
  1188. }
  1189. // finally get soft credit contact id.
  1190. $values['soft_credit_to'] = $contact->id;
  1191. } else {
  1192. // get the contact id from dupicate contact rule, if more than one contact is returned
  1193. // we should return error, since current interface allows only one-one mapping
  1194. $softParams = $params['soft_credit'];
  1195. $softParams['contact_type'] = $params['contact_type'];
  1196. $error = _civicrm_api3_duplicate_formatted_contact( $softParams );
  1197. if ( isset( $error['error_message']['params'][0] ) ) {
  1198. $matchedIDs = explode(',',$error['error_message']['params'][0]);
  1199. // check if only one contact is found
  1200. if ( count( $matchedIDs ) > 1 ) {
  1201. return civicrm_api3_create_error( $error['error_message']['message'], 'soft_credit' );
  1202. } else {
  1203. $values['soft_credit_to'] = $matchedIDs[0];
  1204. }
  1205. } else {
  1206. return civicrm_api3_create_error( 'No match found for specified Soft Credit contact data. Row was skipped.', 'soft_credit' );
  1207. }
  1208. }
  1209. break;
  1210. case 'pledge_payment':
  1211. case 'pledge_id':
  1212. //giving respect to pledge_payment flag.
  1213. if ( !CRM_Utils_Array::value( 'pledge_payment', $params ) ) {
  1214. continue;
  1215. }
  1216. //get total amount of from import fields
  1217. $totalAmount = CRM_Utils_Array::value( 'total_amount', $params );
  1218. $onDuplicate = CRM_Utils_Array::value( 'onDuplicate', $params );
  1219. //we need to get contact id $contributionContactID to
  1220. //retrieve pledge details as well as to validate pledge ID
  1221. //first need to check for update mode
  1222. if ( $onDuplicate == CRM_Contribute_Import_Parser::DUPLICATE_UPDATE &&
  1223. ( $params['contribution_id'] || $params['trxn_id'] ||$params['invoice_id'] ) ) {
  1224. $contribution = new CRM_Contribute_DAO_Contribution();
  1225. if ( $params['contribution_id'] ) {
  1226. $contribution->id = $params['contribution_id'];
  1227. } else if ( $params['trxn_id'] ) {
  1228. $contribution->trxn_id = $params['trxn_id'];
  1229. } else if ( $params['invoice_id'] ) {
  1230. $contribution->invoice_id = $params['invoice_id'];
  1231. }
  1232. if ( $contribution->find(true) ) {
  1233. $contributionContactID = $contribution->contact_id;
  1234. if ( !$totalAmount ) {
  1235. $totalAmount = $contribution->total_amount;
  1236. }
  1237. } else {
  1238. return civicrm_api3_create_error( 'No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment' );
  1239. }
  1240. } else {
  1241. // first get the contact id for given contribution record.
  1242. if ( CRM_Utils_Array::value( 'contribution_contact_id', $params ) ) {
  1243. $contributionContactID = $params['contribution_contact_id'];
  1244. } else if ( CRM_Utils_Array::value( 'external_identifier', $params ) ) {
  1245. require_once 'CRM/Contact/DAO/Contact.php';
  1246. $contact = new CRM_Contact_DAO_Contact();
  1247. $contact->external_identifier = $params['external_identifier'];
  1248. if ( $contact->find(true) ) {
  1249. $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id;
  1250. } else {
  1251. return civicrm_api3_create_error( 'No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment' );
  1252. }
  1253. } else {
  1254. // we need to get contribution contact using de dupe
  1255. $error = civicrm_api3_check_contact_dedupe( $params );
  1256. if ( isset( $error['error_message']['params'][0] ) ) {
  1257. $matchedIDs = explode(',',$error['error_message']['params'][0]);
  1258. // check if only one contact is found
  1259. if ( count( $matchedIDs ) > 1 ) {
  1260. return civicrm_api3_create_error( $error['error_message']['message'], 'pledge_payment' );
  1261. } else {
  1262. $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0];
  1263. }
  1264. } else {
  1265. return civicrm_api3_create_error( 'No match found for specified contact in contribution data. Row was skipped.', 'pledge_payment' );
  1266. }
  1267. }
  1268. }
  1269. if ( CRM_Utils_Array::value('pledge_id', $params ) ) {
  1270. if ( CRM_Core_DAO::getFieldValue( 'CRM_Pledge_DAO_Pledge', $params['pledge_id'] ,'contact_id' ) != $contributionContactID ) {
  1271. return civicrm_api3_create_error( 'Invalid Pledge ID provided. Contribution row was skipped.', 'pledge_payment' );
  1272. }
  1273. $values['pledge_id'] = $params['pledge_id'];
  1274. } else {
  1275. //check if there are any pledge related to this contact, with payments pending or in progress
  1276. require_once 'CRM/Pledge/BAO/Pledge.php';
  1277. $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges( $contributionContactID );
  1278. if ( empty( $pledgeDetails ) ) {
  1279. return civicrm_api3_create_error( 'No open pledges found for this contact. Contribution row was skipped.', 'pledge_payment' );
  1280. } else if ( count( $pledgeDetails ) > 1 ) {
  1281. return civicrm_api3_create_error( 'This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.', 'pledge_payment' );
  1282. }
  1283. // this mean we have only one pending / in progress pledge
  1284. $values['pledge_id'] = $pledgeDetails[0];
  1285. }
  1286. //we need to check if oldest payment amount equal to contribution amount
  1287. require_once 'CRM/Pledge/BAO/Payment.php';
  1288. $pledgePaymentDetails = CRM_Pledge_BAO_Payment::getOldestPledgePayment( $values['pledge_id'] );
  1289. if ( $pledgePaymentDetails['amount'] == $totalAmount ) {
  1290. $values['pledge_payment_id'] = $pledgePaymentDetails['id'];
  1291. } else {
  1292. return civicrm_api3_create_error( 'Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.', 'pledge_payment' );
  1293. }
  1294. break;
  1295. default:
  1296. break;
  1297. }
  1298. }
  1299. if ( array_key_exists( 'note', $params ) ) {
  1300. $values['note'] = $params['note'];
  1301. }
  1302. if ( $create ) {
  1303. // CRM_Contribute_BAO_Contribution::add() handles contribution_source
  1304. // So, if $values contains contribution_source, convert it to source
  1305. $changes = array( 'contribution_source' => 'source' );
  1306. foreach ($changes as $orgVal => $changeVal) {
  1307. if ( isset($values[$orgVal]) ) {
  1308. $values[$changeVal] = $values[$orgVal];
  1309. unset($values[$orgVal]);
  1310. }
  1311. }
  1312. }
  1313. return null;
  1314. }
  1315. /**
  1316. * take the input parameter list as specified in the data model and
  1317. * convert it into the same format that we use in QF and BAO object
  1318. *
  1319. * @todo shouldn't it be moved to Membership.php?
  1320. *
  1321. * @param array $params Associative array of property name/value
  1322. * pairs to insert in new contact.
  1323. * @param array $values The reformatted properties that we can use internally
  1324. *
  1325. * @param array $create Is the formatted Values array going to
  1326. * be used for CRM_Member_BAO_Membership:create()
  1327. *
  1328. * @return array|CRM_Error
  1329. * @access public
  1330. */
  1331. function _civicrm_api3_membership_formatted_param( $params, &$values, $create=false)
  1332. {
  1333. require_once "CRM/Member/DAO/Membership.php";
  1334. $fields =& CRM_Member_DAO_Membership::fields( );
  1335. _civicrm_api3_store_values( $fields, $params, $values );
  1336. require_once 'CRM/Core/OptionGroup.php';
  1337. $customFields = CRM_Core_BAO_CustomField::getFields( 'Membership', false, false, null, null, false, false, false );
  1338. foreach ($params as $key => $value) {
  1339. // ignore empty values or empty arrays etc
  1340. if ( CRM_Utils_System::isNull( $value ) ) {
  1341. continue;
  1342. }
  1343. //Handling Custom Data
  1344. if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
  1345. $values[$key] = $value;
  1346. $type = $customFields[$customFieldID]['html_type'];
  1347. if( $type == 'CheckBox' || $type == 'Multi-Select' ) {
  1348. $mulValues = explode( ',' , $value );
  1349. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1350. $values[$key] = array();
  1351. foreach( $mulValues as $v1 ) {
  1352. foreach($customOption as $customValueID => $customLabel) {
  1353. $customValue = $customLabel['value'];
  1354. if (( strtolower($customLabel['label']) == strtolower(trim($v1)) ) ||
  1355. ( strtolower($customValue) == strtolower(trim($v1)) )) {
  1356. if ( $type == 'CheckBox' ) {
  1357. $values[$key][$customValue] = 1;
  1358. } else {
  1359. $values[$key][] = $customValue;
  1360. }
  1361. }
  1362. }
  1363. }
  1364. } else if ( $type == 'Select' || $type == 'Radio' ) {
  1365. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1366. foreach( $customOption as $customFldID => $customValue ) {
  1367. $val = CRM_Utils_Array::value( 'value', $customValue );
  1368. $label = CRM_Utils_Array::value( 'label', $customValue );
  1369. $label = strtolower( $label );
  1370. $value = strtolower( trim( $value ) );
  1371. if ( ( $value == $label ) || ( $value == strtolower( $val ) ) ) {
  1372. $values[$key] = $val;
  1373. }
  1374. }
  1375. }
  1376. }
  1377. switch ($key) {
  1378. case 'membership_contact_id':
  1379. if (!CRM_Utils_Rule::integer($value)) {
  1380. return civicrm_api3_create_error("contact_id not valid: $value");
  1381. }
  1382. $dao = new CRM_Core_DAO();
  1383. $qParams = array();
  1384. $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
  1385. $qParams);
  1386. if (!$svq) {
  1387. return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value.");
  1388. }
  1389. $values['contact_id'] = $values['membership_contact_id'];
  1390. unset($values['membership_contact_id']);
  1391. break;
  1392. case 'join_date':
  1393. case 'membership_start_date':
  1394. case 'membership_end_date':
  1395. if (!CRM_Utils_Rule::date($value)) {
  1396. return civicrm_api3_create_error("$key not a valid date: $value");
  1397. }
  1398. break;
  1399. case 'membership_type_id':
  1400. $id = CRM_Core_DAO::getFieldValue( "CRM_Member_DAO_MembershipType", $value, 'id', 'name' );
  1401. $values[$key] = $id;
  1402. break;
  1403. case 'status_id':
  1404. $id = CRM_Core_DAO::getFieldValue( "CRM_Member_DAO_MembershipStatus", $value, 'id', 'name' );
  1405. $values[$key] = $id;
  1406. break;
  1407. case 'member_is_test':
  1408. $values['is_test'] = CRM_Utils_Array::value( $key, $params, false );
  1409. unset($values['member_is_test']);
  1410. break;
  1411. default:
  1412. break;
  1413. }
  1414. }
  1415. if ( $create ) {
  1416. // CRM_Member_BAO_Membership::create() handles membership_start_date,
  1417. // membership_end_date and membership_source. So, if $values contains
  1418. // membership_start_date, membership_end_date or membership_source,
  1419. // convert it to start_date, end_date or source
  1420. $changes = array('membership_start_date' => 'start_date',
  1421. 'membership_end_date' => 'end_date',
  1422. 'membership_source' => 'source',
  1423. );
  1424. foreach ($changes as $orgVal => $changeVal) {
  1425. if ( isset($values[$orgVal]) ) {
  1426. $values[$changeVal] = $values[$orgVal];
  1427. unset($values[$orgVal]);
  1428. }
  1429. }
  1430. }
  1431. return null;
  1432. }
  1433. /**
  1434. * take the input parameter list as specified in the data model and
  1435. * convert it into the same format that we use in QF and BAO object
  1436. *
  1437. * @param array $params Associative array of property name/value
  1438. * pairs to insert in new contact.
  1439. * @param array $values The reformatted properties that we can use internally
  1440. *
  1441. * @param array $create Is the formatted Values array going to
  1442. * be used for CRM_Activity_BAO_Activity::create()
  1443. *
  1444. * @return array|CRM_Error
  1445. * @access public
  1446. */
  1447. function _civicrm_api3_activity_formatted_param( $params, &$values, $create=false)
  1448. {
  1449. $fields =& CRM_Activity_DAO_Activity::fields( );
  1450. _civicrm_api3_store_values( $fields, $params, $values );
  1451. require_once 'CRM/Core/OptionGroup.php';
  1452. $customFields = CRM_Core_BAO_CustomField::getFields( 'Activity', false, false, null, null, false, false, false );
  1453. foreach ($params as $key => $value) {
  1454. // ignore empty values or empty arrays etc
  1455. if ( CRM_Utils_System::isNull( $value ) ) {
  1456. continue;
  1457. }
  1458. //Handling Custom Data
  1459. if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
  1460. $values[$key] = $value;
  1461. $type = $customFields[$customFieldID]['html_type'];
  1462. if( $type == 'CheckBox' || $type == 'Multi-Select' ) {
  1463. $mulValues = explode( ',' , $value );
  1464. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1465. $values[$key] = array();
  1466. foreach( $mulValues as $v1 ) {
  1467. foreach($customOption as $customValueID => $customLabel) {
  1468. $customValue = $customLabel['value'];
  1469. if (( strtolower($customLabel['label']) == strtolower(trim($v1)) ) ||
  1470. ( strtolower($customValue) == strtolower(trim($v1)) )) {
  1471. if ( $type == 'CheckBox' ) {
  1472. $values[$key][$customValue] = 1;
  1473. } else {
  1474. $values[$key][] = $customValue;
  1475. }
  1476. }
  1477. }
  1478. }
  1479. } else if ( $type == 'Select' || $type == 'Radio' ) {
  1480. $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, true);
  1481. foreach( $customOption as $customFldID => $customValue ) {
  1482. $val = CRM_Utils_Array::value( 'value', $customValue );
  1483. $label = CRM_Utils_Array::value( 'label', $customValue );
  1484. $label = strtolower( $label );
  1485. $value = strtolower( trim( $value ) );
  1486. if ( ( $value == $label ) || ( $value == strtolower( $val ) ) ) {
  1487. $values[$key] = $val;
  1488. }
  1489. }
  1490. }
  1491. } else if ( $key == 'target_contact_id' ) {
  1492. if ( !CRM_Utils_Rule::integer( $value ) ) {
  1493. return civicrm_api3_create_error("contact_id not valid: $value");
  1494. }
  1495. $contactID = CRM_Core_DAO::singleValueQuery( "SELECT id FROM civicrm_contact WHERE id = $value" );
  1496. if ( !$contactID ) {
  1497. return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value.");
  1498. }
  1499. }
  1500. }
  1501. return null;
  1502. }
  1503. /**
  1504. * Function to check duplicate contacts based on de-deupe parameters
  1505. */
  1506. function civicrm_api3_check_contact_dedupe( $params ) {
  1507. static $cIndieFields = null;
  1508. static $defaultLocationId = null;
  1509. $contactType = $params['contact_type'] ;
  1510. if ( $cIndieFields == null ) {
  1511. require_once 'CRM/Contact/BAO/Contact.php';
  1512. $cTempIndieFields = CRM_Contact_BAO_Contact::importableFields( $contactType );
  1513. $cIndieFields = $cTempIndieFields;
  1514. require_once "CRM/Core/BAO/LocationType.php";
  1515. $defaultLocation =& CRM_Core_BAO_LocationType::getDefault();
  1516. //set the value to default location id else set to 1
  1517. if ( !$defaultLocationId = (int)$defaultLocation->id ) $defaultLocationId = 1;
  1518. }
  1519. require_once 'CRM/Contact/BAO/Query.php';
  1520. $locationFields = CRM_Contact_BAO_Query::$_locationSpecificFields;
  1521. $contactFormatted = array( );
  1522. foreach ( $params as $key => $field ) {
  1523. if ($field == null || $field === '') {
  1524. continue;
  1525. }
  1526. if (is_array($field)) {
  1527. foreach ($field as $value) {
  1528. $break = false;
  1529. if ( is_array($value) ) {
  1530. foreach ($value as $name => $testForEmpty) {
  1531. if ($name !== 'phone_type' &&
  1532. ($testForEmpty === '' || $testForEmpty == null)) {
  1533. $break = true;
  1534. break;
  1535. }
  1536. }
  1537. } else {
  1538. $break = true;
  1539. }
  1540. if ( !$break ) {
  1541. _civicrm_api3_add_formatted_param($value, $contactFormatted );
  1542. }
  1543. }
  1544. continue;
  1545. }
  1546. $value = array($key => $field);
  1547. // check if location related field, then we need to add primary location type
  1548. if ( in_array($key, $locationFields) ) {
  1549. $value['location_type_id'] = $defaultLocationId;
  1550. } else if (array_key_exists($key, $cIndieFields)) {
  1551. $value['contact_type'] = $contactType;
  1552. }
  1553. _civicrm_api3_add_formatted_param( $value, $contactFormatted );
  1554. }
  1555. $contactFormatted['contact_type'] = $contactType;
  1556. return _civicrm_api3_duplicate_formatted_contact( $contactFormatted );
  1557. }
  1558. /**
  1559. * Check permissions for a given API call.
  1560. *
  1561. * @param $entity string API entity being accessed
  1562. * @param $action string API action being performed
  1563. * @param $params array params of the API call
  1564. * @param $throw bool whether to throw exception instead of returning false
  1565. *
  1566. * @return bool whether the current API user has the permission to make the call
  1567. */
  1568. function civicrm_api3_api_check_permission($entity, $action, &$params, $throw = true)
  1569. {
  1570. // return early unless we’re told explicitly to do the permission check
  1571. if (empty($params['check_permissions']) or $params['check_permissions'] == false) return true;
  1572. require_once 'CRM/Core/Permission.php';
  1573. require_once 'CRM/Core/DAO/.permissions.php';
  1574. $permissions = _civicrm_api3_permissions($entity, $action, $params);
  1575. // $params might’ve been reset by the alterAPIPermissions() hook
  1576. if (isset($params['check_permissions']) and $params['check_permissions'] == false) return true;
  1577. foreach ($permissions as $perm) {
  1578. if (!CRM_Core_Permission::check($perm)) {
  1579. if ($throw) {
  1580. throw new Exception("API permission check failed for $entity/$action call; missing permission: $perm.");
  1581. } else {
  1582. return false;
  1583. }
  1584. }
  1585. }
  1586. return true;
  1587. }
  1588. /*
  1589. * Function to do a 'standard' api get - when the api is only doing a $bao->find then use this
  1590. *
  1591. * @param string $bao_name name of BAO
  1592. * @param array $params params from api
  1593. * @param bool $returnAsSuccess return in api success format
  1594. */
  1595. function _civicrm_api3_basic_get($bao_name, &$params, $returnAsSuccess = TRUE){
  1596. $bao = new $bao_name();
  1597. _civicrm_api3_dao_set_filter ( $bao, $params, FALSE );
  1598. if($returnAsSuccess){
  1599. return civicrm_api3_create_success(_civicrm_api3_dao_to_array ($bao,$params, FALSE),$params,$bao);
  1600. }else{
  1601. return _civicrm_api3_dao_to_array ($bao,$params, FALSE);
  1602. }
  1603. }
  1604. /*
  1605. * Function to do a 'standard' api create - when the api is only doing a $bao::create then use this
  1606. */
  1607. function _civicrm_api3_basic_create($bao_name, &$params){
  1608. $args = array(&$params);
  1609. $bao = call_user_func_array(array($bao_name, 'create'), $args);
  1610. if ( is_null( $bao) ) {
  1611. return civicrm_api3_create_error( 'Entity not created' );
  1612. } else {
  1613. $values = array();
  1614. _civicrm_api3_object_to_array($bao, $values[ $bao->id]);
  1615. return civicrm_api3_create_success($values,$params,$bao );
  1616. }
  1617. }
  1618. /*
  1619. * Function to do a 'standard' api del - when the api is only doing a $bao::del then use this
  1620. */
  1621. function _civicrm_api3_basic_delete($bao_name, &$params){
  1622. civicrm_api3_verify_mandatory($params,null,array('id'));
  1623. $args = array(&$params['id']);
  1624. $bao = call_user_func_array(array($bao_name, 'del'), $args);
  1625. return civicrm_api3_create_success( true );
  1626. }
  1627. /*
  1628. * Get custom data for the given entity & Add it to the returnArray as 'custom_123' = 'custom string' AND 'custom_123_1' = 'custom string'
  1629. * Where 123 is field value & 1 is the id within the custom group data table (value ID)
  1630. *
  1631. * @param array $returnArray - array to append custom data too - generally $result[4] where 4 is the entity id.
  1632. * @param string $entity e.g membership, event
  1633. * @param int $groupID - per CRM_Core_BAO_CustomGroup::getTree
  1634. * @param int $subType e.g. membership_type_id where custom data doesn't apply to all membership types
  1635. * @param string $subName - Subtype of entity
  1636. *
  1637. */
  1638. function _civicrm_apiv3_custom_data_get(&$returnArray,$entity,$entity_id ,$groupID = null,$subType = null, $subName = null){
  1639. require_once 'CRM/Core/BAO/CustomGroup.php';
  1640. $groupTree =& CRM_Core_BAO_CustomGroup::getTree($entity,
  1641. CRM_Core_DAO::$_nullObject,
  1642. $entity_id ,
  1643. $groupID,
  1644. $subType,
  1645. $subName);
  1646. $groupTree = CRM_Core_BAO_CustomGroup::formatGroupTree( $groupTree, 1, CRM_Core_DAO::$_nullObject );
  1647. $customValues = array( );
  1648. CRM_Core_BAO_CustomGroup::setDefaults( $groupTree, $customValues );
  1649. if ( !empty( $customValues ) ) {
  1650. foreach ( $customValues as $key => $val ) {
  1651. // per standard - return custom_fieldID
  1652. $returnArray['custom_' . (CRM_Core_BAO_CustomField::getKeyID($key))] = $val;
  1653. //not standard - but some api did this so guess we should keep - cheap as chips
  1654. $returnArray[$key] = $val;
  1655. }
  1656. }
  1657. }