Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
6a488035 TO |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
81621fee | 4 | | CiviCRM version 4.7 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
e7112fa7 | 6 | | Copyright CiviCRM LLC (c) 2004-2015 | |
6a488035 TO |
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 | +--------------------------------------------------------------------+ | |
d25dd0ee | 26 | */ |
6a488035 TO |
27 | |
28 | require_once 'CiviTest/CiviUnitTestCase.php'; | |
29 | require_once 'CRM/Utils/DeprecatedUtils.php'; | |
30 | ||
31 | /** | |
32 | * Test class for API utils | |
33 | * | |
34 | * @package CiviCRM | |
35 | */ | |
36 | class api_v3_UtilsTest extends CiviUnitTestCase { | |
ca985406 | 37 | protected $_apiversion = 3; |
6a488035 | 38 | public $DBResetRequired = FALSE; |
b7c9bc4c | 39 | |
6a488035 TO |
40 | public $_contactID = 1; |
41 | ||
42 | /** | |
43 | * Sets up the fixture, for example, opens a network connection. | |
fe482240 | 44 | * |
6a488035 | 45 | * This method is called before a test is executed. |
6a488035 TO |
46 | */ |
47 | protected function setUp() { | |
48 | parent::setUp(); | |
d1e734a5 | 49 | $this->useTransaction(TRUE); |
6a488035 TO |
50 | } |
51 | ||
00be9182 | 52 | public function testAddFormattedParam() { |
6a488035 TO |
53 | $values = array('contact_type' => 'Individual'); |
54 | $params = array('something' => 1); | |
55 | $result = _civicrm_api3_deprecated_add_formatted_param($values, $params); | |
56 | $this->assertTrue($result); | |
57 | } | |
58 | ||
00be9182 | 59 | public function testCheckPermissionReturn() { |
6a488035 TO |
60 | $check = array('check_permissions' => TRUE); |
61 | $config = CRM_Core_Config::singleton(); | |
62 | $config->userPermissionClass->permissions = array(); | |
d0c9daa4 | 63 | $this->assertFalse($this->runPermissionCheck('contact', 'create', $check), 'empty permissions should not be enough'); |
6a488035 | 64 | $config->userPermissionClass->permissions = array('access CiviCRM'); |
d0c9daa4 | 65 | $this->assertFalse($this->runPermissionCheck('contact', 'create', $check), 'lacking permissions should not be enough'); |
6a488035 | 66 | $config->userPermissionClass->permissions = array('add contacts'); |
d0c9daa4 | 67 | $this->assertFalse($this->runPermissionCheck('contact', 'create', $check), 'lacking permissions should not be enough'); |
6a488035 TO |
68 | |
69 | $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts'); | |
d0c9daa4 | 70 | $this->assertTrue($this->runPermissionCheck('contact', 'create', $check), 'exact permissions should be enough'); |
6a488035 TO |
71 | |
72 | $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts'); | |
d0c9daa4 | 73 | $this->assertTrue($this->runPermissionCheck('contact', 'create', $check), 'overfluous permissions should be enough'); |
6a488035 TO |
74 | } |
75 | ||
00be9182 | 76 | public function testCheckPermissionThrow() { |
6a488035 TO |
77 | $check = array('check_permissions' => TRUE); |
78 | $config = CRM_Core_Config::singleton(); | |
79 | try { | |
80 | $config->userPermissionClass->permissions = array('access CiviCRM'); | |
d0c9daa4 | 81 | $this->runPermissionCheck('contact', 'create', $check, TRUE); |
6a488035 | 82 | } |
92915c55 | 83 | catch (Exception $e) { |
6a488035 TO |
84 | $message = $e->getMessage(); |
85 | } | |
1644b908 | 86 | $this->assertEquals($message, 'API permission check failed for Contact/create call; insufficient permission: require access CiviCRM and add contacts', 'lacking permissions should throw an exception'); |
6a488035 TO |
87 | |
88 | $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts'); | |
d0c9daa4 | 89 | $this->assertTrue($this->runPermissionCheck('contact', 'create', $check), 'overfluous permissions should return true'); |
6a488035 TO |
90 | } |
91 | ||
00be9182 | 92 | public function testCheckPermissionSkip() { |
6a488035 TO |
93 | $config = CRM_Core_Config::singleton(); |
94 | $config->userPermissionClass->permissions = array('access CiviCRM'); | |
95 | $params = array('check_permissions' => TRUE); | |
d0c9daa4 | 96 | $this->assertFalse($this->runPermissionCheck('contact', 'create', $params), 'lacking permissions should not be enough'); |
6a488035 | 97 | $params = array('check_permissions' => FALSE); |
d0c9daa4 TO |
98 | $this->assertTrue($this->runPermissionCheck('contact', 'create', $params), 'permission check should be skippable'); |
99 | } | |
100 | ||
101 | /** | |
102 | * @param string $entity | |
103 | * @param string $action | |
104 | * @param array $params | |
e16033b4 TO |
105 | * @param bool $throws |
106 | * Whether we should pass any exceptions for authorization failures. | |
cbdcc634 EM |
107 | * |
108 | * @throws API_Exception | |
109 | * @throws Exception | |
a6c01b45 CW |
110 | * @return bool |
111 | * TRUE or FALSE depending on the outcome of the authorization check | |
d0c9daa4 | 112 | */ |
00be9182 | 113 | public function runPermissionCheck($entity, $action, $params, $throws = FALSE) { |
d0c9daa4 TO |
114 | $dispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); |
115 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\PermissionCheck()); | |
116 | $kernel = new \Civi\API\Kernel($dispatcher); | |
cde12543 | 117 | $apiRequest = \Civi\API\Request::create($entity, $action, $params, NULL); |
d0c9daa4 TO |
118 | try { |
119 | $kernel->authorize(NULL, $apiRequest); | |
120 | return TRUE; | |
0db6c3e1 TO |
121 | } |
122 | catch (\API_Exception $e) { | |
d0c9daa4 TO |
123 | $extra = $e->getExtraParams(); |
124 | if (!$throws && $extra['error_code'] == API_Exception::UNAUTHORIZED) { | |
125 | return FALSE; | |
0db6c3e1 TO |
126 | } |
127 | else { | |
d0c9daa4 TO |
128 | throw $e; |
129 | } | |
130 | } | |
6a488035 TO |
131 | } |
132 | ||
c490a46a CW |
133 | /** |
134 | * Test verify mandatory - includes DAO & passed as well as empty & NULL fields | |
135 | */ | |
00be9182 | 136 | public function testVerifyMandatory() { |
6a488035 TO |
137 | _civicrm_api3_initialize(TRUE); |
138 | $params = array( | |
139 | 'entity_table' => 'civicrm_contact', | |
140 | 'note' => '', | |
141 | 'contact_id' => $this->_contactID, | |
142 | 'modified_date' => '2011-01-31', | |
143 | 'subject' => NULL, | |
21dfd5f5 | 144 | 'version' => $this->_apiversion, |
6a488035 TO |
145 | ); |
146 | try { | |
147 | $result = civicrm_api3_verify_mandatory($params, 'CRM_Core_BAO_Note', array('note', 'subject')); | |
148 | } | |
92915c55 | 149 | catch (Exception $expected) { |
6a488035 TO |
150 | $this->assertEquals('Mandatory key(s) missing from params array: entity_id, note, subject', $expected->getMessage()); |
151 | return; | |
152 | } | |
153 | ||
154 | $this->fail('An expected exception has not been raised.'); | |
155 | } | |
156 | ||
c490a46a CW |
157 | /** |
158 | * Test verify one mandatory - includes DAO & passed as well as empty & NULL fields | |
159 | */ | |
00be9182 | 160 | public function testVerifyOneMandatory() { |
6a488035 TO |
161 | _civicrm_api3_initialize(TRUE); |
162 | $params = array( | |
163 | 'entity_table' => 'civicrm_contact', | |
164 | 'note' => '', | |
165 | 'contact_id' => $this->_contactID, | |
166 | 'modified_date' => '2011-01-31', | |
167 | 'subject' => NULL, | |
168 | 'version' => $this->_apiversion, | |
169 | ); | |
170 | ||
171 | try { | |
172 | $result = civicrm_api3_verify_one_mandatory($params, 'CRM_Core_BAO_Note', array('note', 'subject')); | |
173 | } | |
92915c55 | 174 | catch (Exception $expected) { |
6a488035 TO |
175 | $this->assertEquals('Mandatory key(s) missing from params array: entity_id, one of (note, subject)', $expected->getMessage()); |
176 | return; | |
177 | } | |
178 | ||
179 | $this->fail('An expected exception has not been raised.'); | |
180 | } | |
181 | ||
c490a46a CW |
182 | /** |
183 | * Test verify one mandatory - includes DAO & passed as well as empty & NULL fields | |
184 | */ | |
00be9182 | 185 | public function testVerifyOneMandatoryOneSet() { |
6a488035 | 186 | _civicrm_api3_initialize(TRUE); |
92915c55 TO |
187 | $params = array( |
188 | 'version' => 3, | |
189 | 'entity_table' => 'civicrm_contact', | |
190 | 'note' => 'note', | |
191 | 'contact_id' => $this->_contactID, | |
192 | 'modified_date' => '2011-01-31', | |
389bcebf | 193 | 'subject' => NULL, |
92915c55 | 194 | ); |
6a488035 TO |
195 | |
196 | try { | |
197 | civicrm_api3_verify_one_mandatory($params, NULL, array('note', 'subject')); | |
198 | } | |
92915c55 | 199 | catch (Exception$expected) { |
6a488035 TO |
200 | $this->fail('Exception raised when it shouldn\'t have been in line ' . __LINE__); |
201 | } | |
202 | } | |
203 | ||
204 | ||
c490a46a | 205 | /** |
eceb18cc | 206 | * Test GET DAO function returns DAO. |
b6708aeb | 207 | */ |
00be9182 | 208 | public function testGetDAO() { |
49e101d0 CW |
209 | $params = array( |
210 | 'civicrm_api3_custom_group_get' => 'CRM_Core_DAO_CustomGroup', | |
211 | 'custom_group' => 'CRM_Core_DAO_CustomGroup', | |
212 | 'CustomGroup' => 'CRM_Core_DAO_CustomGroup', | |
213 | 'civicrm_api3_custom_field_get' => 'CRM_Core_DAO_CustomField', | |
214 | 'civicrm_api3_survey_get' => 'CRM_Campaign_DAO_Survey', | |
215 | 'civicrm_api3_pledge_payment_get' => 'CRM_Pledge_DAO_PledgePayment', | |
216 | 'civicrm_api3_website_get' => 'CRM_Core_DAO_Website', | |
217 | 'Membership' => 'CRM_Member_DAO_Membership', | |
218 | ); | |
219 | foreach ($params as $input => $expected) { | |
220 | $result = _civicrm_api3_get_DAO($input); | |
221 | $this->assertEquals($expected, $result); | |
222 | } | |
6a488035 | 223 | } |
c490a46a CW |
224 | |
225 | /** | |
eceb18cc | 226 | * Test GET BAO function returns BAO when it exists. |
b6708aeb | 227 | */ |
00be9182 | 228 | public function testGetBAO() { |
49e101d0 CW |
229 | $params = array( |
230 | 'civicrm_api3_website_get' => 'CRM_Core_BAO_Website', | |
231 | 'civicrm_api3_survey_get' => 'CRM_Campaign_BAO_Survey', | |
232 | 'civicrm_api3_pledge_payment_get' => 'CRM_Pledge_BAO_PledgePayment', | |
233 | 'Household' => 'CRM_Contact_BAO_Contact', | |
234 | // Note this one DOES NOT have a BAO so we expect to fall back on returning the DAO | |
235 | 'mailing_group' => 'CRM_Mailing_DAO_MailingGroup', | |
5c1174d3 CW |
236 | // Make sure we get null back with nonexistant entities |
237 | 'civicrm_this_does_not_exist' => NULL, | |
49e101d0 CW |
238 | ); |
239 | foreach ($params as $input => $expected) { | |
240 | $result = _civicrm_api3_get_BAO($input); | |
241 | $this->assertEquals($expected, $result); | |
242 | } | |
6a488035 TO |
243 | } |
244 | ||
00be9182 | 245 | public function test_civicrm_api3_validate_fields() { |
6a488035 | 246 | $params = array('start_date' => '2010-12-20', 'end_date' => ''); |
7f8c98cd E |
247 | $fields = civicrm_api3('relationship', 'getfields', array('action' => 'get')); |
248 | _civicrm_api3_validate_fields('relationship', 'get', $params, $fields['values']); | |
6a488035 TO |
249 | $this->assertEquals('20101220000000', $params['start_date']); |
250 | $this->assertEquals('', $params['end_date']); | |
251 | } | |
252 | ||
00be9182 | 253 | public function test_civicrm_api3_validate_fields_membership() { |
92915c55 TO |
254 | $params = array( |
255 | 'start_date' => '2010-12-20', | |
256 | 'end_date' => '', | |
257 | 'membership_end_date' => '0', | |
258 | 'join_date' => '2010-12-20', | |
389bcebf | 259 | 'membership_start_date' => '2010-12-20', |
92915c55 | 260 | ); |
7f8c98cd E |
261 | $fields = civicrm_api3('Membership', 'getfields', array('action' => 'get')); |
262 | _civicrm_api3_validate_fields('Membership', 'get', $params, $fields['values']); | |
903d0d38 | 263 | $this->assertEquals('2010-12-20', $params['start_date']); |
ba4a1892 | 264 | $this->assertEquals('20101220000000', $params['membership_start_date']); |
6a488035 TO |
265 | $this->assertEquals('', $params['end_date']); |
266 | $this->assertEquals('20101220000000', $params['join_date'], 'join_date not set in line ' . __LINE__); | |
267 | } | |
268 | ||
00be9182 | 269 | public function test_civicrm_api3_validate_fields_event() { |
6a488035 TO |
270 | |
271 | $params = array( | |
272 | 'registration_start_date' => 20080601, | |
6c6e6187 | 273 | 'registration_end_date' => '2008-10-15', |
92915c55 TO |
274 | 'start_date' => '2010-12-20', |
275 | 'end_date' => '', | |
6a488035 | 276 | ); |
7f8c98cd E |
277 | $fields = civicrm_api3('Event', 'getfields', array('action' => 'create')); |
278 | _civicrm_api3_validate_fields('event', 'create', $params, $fields['values']); | |
ba4a1892 TM |
279 | $this->assertEquals('20101220000000', $params['start_date']); |
280 | $this->assertEquals('20081015000000', $params['registration_end_date']); | |
281 | $this->assertEquals('', $params['end_date']); | |
6a488035 TO |
282 | $this->assertEquals('20080601000000', $params['registration_start_date']); |
283 | } | |
284 | ||
00be9182 | 285 | public function test_civicrm_api3_validate_fields_exception() { |
6a488035 TO |
286 | $params = array( |
287 | 'join_date' => 'abc', | |
288 | ); | |
289 | try { | |
7f8c98cd E |
290 | $fields = civicrm_api3('Membership', 'getfields', array('action' => 'get')); |
291 | _civicrm_api3_validate_fields('Membership', 'get', $params, $fields['values']); | |
6a488035 | 292 | } |
92915c55 | 293 | catch (Exception$expected) { |
6a488035 TO |
294 | $this->assertEquals('join_date is not a valid date: abc', $expected->getMessage()); |
295 | } | |
296 | } | |
297 | ||
00be9182 | 298 | public function testGetFields() { |
ca985406 | 299 | $result = $this->callAPISuccess('membership', 'getfields', array()); |
6a488035 | 300 | $this->assertArrayHasKey('values', $result); |
ca985406 | 301 | $result = $this->callAPISuccess('relationship', 'getfields', array()); |
6a488035 | 302 | $this->assertArrayHasKey('values', $result); |
ca985406 | 303 | $result = $this->callAPISuccess('event', 'getfields', array()); |
6a488035 TO |
304 | $this->assertArrayHasKey('values', $result); |
305 | } | |
41d89fcb | 306 | |
00be9182 | 307 | public function testGetFields_AllOptions() { |
ca985406 | 308 | $result = $this->callAPISuccess('contact', 'getfields', array( |
41d89fcb TO |
309 | 'options' => array( |
310 | 'get_options' => 'all', | |
311 | ), | |
41d89fcb | 312 | )); |
41d89fcb TO |
313 | $this->assertEquals('Household', $result['values']['contact_type']['options']['Household']); |
314 | $this->assertEquals('HTML', $result['values']['preferred_mail_format']['options']['HTML']); | |
315 | } | |
96025800 | 316 | |
5bc7c754 TO |
317 | public function basicArrayCases() { |
318 | $records = array( | |
319 | array('snack_id' => 'a', 'fruit' => 'apple', 'cheese' => 'swiss'), | |
320 | array('snack_id' => 'b', 'fruit' => 'grape', 'cheese' => 'cheddar'), | |
321 | array('snack_id' => 'c', 'fruit' => 'apple', 'cheese' => 'cheddar'), | |
322 | array('snack_id' => 'd', 'fruit' => 'apple', 'cheese' => 'gouda'), | |
323 | array('snack_id' => 'e', 'fruit' => 'apple', 'cheese' => 'provolone'), | |
324 | ); | |
325 | ||
326 | $cases[] = array( | |
327 | $records, | |
328 | array('version' => 3), // params | |
329 | array('a', 'b', 'c', 'd', 'e'), // expected results | |
330 | ); | |
331 | ||
332 | $cases[] = array( | |
333 | $records, | |
334 | array('version' => 3, 'fruit' => 'apple'), // params | |
335 | array('a', 'c', 'd', 'e'), // expected results | |
336 | ); | |
337 | ||
338 | $cases[] = array( | |
339 | $records, | |
340 | array('version' => 3, 'cheese' => 'cheddar'), | |
341 | array('b', 'c'), | |
342 | ); | |
343 | ||
a066deea TO |
344 | $cases[] = array( |
345 | $records, | |
346 | array('version' => 3, 'id' => 'd'), | |
347 | array('d'), | |
348 | ); | |
349 | ||
5bc7c754 TO |
350 | return $cases; |
351 | } | |
352 | ||
353 | /** | |
354 | * Make a basic API (Widget.get) which allows getting data out of a simple in-memory | |
355 | * list of records. | |
356 | * | |
357 | * @param $records | |
358 | * The list of all records. | |
359 | * @param $params | |
360 | * The filter criteria | |
361 | * @param array $resultIds | |
362 | * The records which are expected to match. | |
363 | * @dataProvider basicArrayCases | |
364 | */ | |
365 | public function testBasicArrayGet($records, $params, $resultIds) { | |
366 | $params['version'] = 3; | |
367 | ||
368 | $kernel = new \Civi\API\Kernel(new \Symfony\Component\EventDispatcher\EventDispatcher()); | |
369 | ||
370 | $provider = new \Civi\API\Provider\AdhocProvider($params['version'], 'Widget'); | |
371 | $provider->addAction('get', 'access CiviCRM', function ($apiRequest) use ($records) { | |
372 | return _civicrm_api3_basic_array_get('Widget', $apiRequest['params'], $records, 'snack_id', array('snack_id', 'fruit', 'cheese')); | |
373 | }); | |
374 | $kernel->registerApiProvider($provider); | |
375 | ||
376 | $r1 = $kernel->run('Widget', 'get', $params); | |
377 | $this->assertEquals(count($resultIds), $r1['count']); | |
378 | $this->assertEquals($resultIds, array_keys($r1['values'])); | |
379 | $this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('snack_id', $r1['values']))); | |
380 | $this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('id', $r1['values']))); | |
381 | ||
382 | $r2 = $kernel->run('Widget', 'get', $params + array('sequential' => 1)); | |
383 | $this->assertEquals(count($resultIds), $r2['count']); | |
384 | $this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('snack_id', $r2['values']))); | |
385 | $this->assertEquals($resultIds, array_values(CRM_Utils_Array::collect('id', $r2['values']))); | |
386 | ||
387 | $r3 = $kernel->run('Widget', 'get', $params + array('options' => array('offset' => 1, 'limit' => 2))); | |
388 | $slice = array_slice($resultIds, 1, 2); | |
389 | $this->assertEquals(count($slice), $r3['count']); | |
390 | $this->assertEquals($slice, array_values(CRM_Utils_Array::collect('snack_id', $r3['values']))); | |
391 | $this->assertEquals($slice, array_values(CRM_Utils_Array::collect('id', $r3['values']))); | |
392 | } | |
393 | ||
394 | public function testBasicArrayGetReturn() { | |
395 | $records = array( | |
396 | array('snack_id' => 'a', 'fruit' => 'apple', 'cheese' => 'swiss'), | |
397 | array('snack_id' => 'b', 'fruit' => 'grape', 'cheese' => 'cheddar'), | |
398 | array('snack_id' => 'c', 'fruit' => 'apple', 'cheese' => 'cheddar'), | |
399 | ); | |
400 | ||
401 | $kernel = new \Civi\API\Kernel(new \Symfony\Component\EventDispatcher\EventDispatcher()); | |
402 | $provider = new \Civi\API\Provider\AdhocProvider(3, 'Widget'); | |
403 | $provider->addAction('get', 'access CiviCRM', function ($apiRequest) use ($records) { | |
404 | return _civicrm_api3_basic_array_get('Widget', $apiRequest['params'], $records, 'snack_id', array('snack_id', 'fruit', 'cheese')); | |
405 | }); | |
406 | $kernel->registerApiProvider($provider); | |
407 | ||
408 | $r1 = $kernel->run('Widget', 'get', array( | |
409 | 'version' => 3, | |
410 | 'snack_id' => 'b', | |
411 | 'return' => 'fruit', | |
412 | )); | |
413 | $this->assertAPISuccess($r1); | |
414 | $this->assertEquals(array('b' => array('id' => 'b', 'fruit' => 'grape')), $r1['values']); | |
415 | ||
416 | $r2 = $kernel->run('Widget', 'get', array( | |
417 | 'version' => 3, | |
418 | 'snack_id' => 'b', | |
419 | 'return' => array('fruit', 'cheese'), | |
420 | )); | |
421 | $this->assertAPISuccess($r2); | |
422 | $this->assertEquals(array('b' => array('id' => 'b', 'fruit' => 'grape', 'cheese' => 'cheddar')), $r2['values']); | |
423 | ||
424 | $r3 = $kernel->run('Widget', 'get', array( | |
425 | 'version' => 3, | |
426 | 'cheese' => 'cheddar', | |
427 | 'return' => array('fruit'), | |
428 | )); | |
429 | $this->assertAPISuccess($r3); | |
430 | $this->assertEquals(array( | |
431 | 'b' => array('id' => 'b', 'fruit' => 'grape'), | |
432 | 'c' => array('id' => 'c', 'fruit' => 'apple'), | |
433 | ), $r3['values']); | |
434 | } | |
435 | ||
6a488035 | 436 | } |