4 * Class CRM_Core_ManagedEntitiesTest
7 class CRM_Core_ManagedEntitiesTest
extends CiviUnitTestCase
{
9 * @var \Civi\API\Kernel
14 * @var \Civi\API\Provider\AdhocProvider
16 protected $adhocProvider;
25 public function setUp() {
26 $this->useTransaction(TRUE);
28 $this->modules
= array(
29 'one' => new CRM_Core_Module('com.example.one', TRUE),
30 'two' => new CRM_Core_Module('com.example.two', TRUE),
33 // Testing on drupal-demo fails because some extensions have mgd ents.
34 CRM_Core_DAO
::singleValueQuery('DELETE FROM civicrm_managed');
36 $this->fixtures
['com.example.one-foo'] = array(
37 'module' => 'com.example.one',
39 'entity' => 'CustomSearch',
42 'class_name' => 'CRM_Example_One_Foo',
46 $this->fixtures
['com.example.one-bar'] = array(
47 'module' => 'com.example.one',
49 'entity' => 'CustomSearch',
52 'class_name' => 'CRM_Example_One_Bar',
56 $this->fixtures
['com.example.one-CustomGroup'] = array(
57 'module' => 'com.example.one',
58 'name' => 'CustomGroup',
59 'entity' => 'CustomGroup',
62 'name' => 'test_custom_group',
63 'title' => 'Test custom group',
64 'extends' => 'Individual',
67 $this->fixtures
['com.example.one-CustomField'] = array(
68 'module' => 'com.example.one',
69 'name' => 'CustomField',
70 'entity' => 'CustomField',
73 'name' => 'test_custom_field',
74 'label' => 'Test custom field',
75 'custom_group_id' => 'test_custom_group',
76 'data_type' => 'String',
77 'html_type' => 'Text',
81 $this->apiKernel
= \Civi
::service('civi_api_kernel');
82 $this->adhocProvider
= new \Civi\API\Provider\
AdhocProvider(3, 'CustomSearch');
83 $this->apiKernel
->registerApiProvider($this->adhocProvider
);
86 public function tearDown() {
92 * Set up an active module and, over time, the hook implementation changes
93 * to (1) create 'foo' entity, (2) create 'bar' entity', (3) remove 'foo'
96 public function testAddRemoveEntitiesModule_UpdateAlways_DeleteAlways() {
99 // create first managed entity ('foo')
100 $decls[] = $this->fixtures
['com.example.one-foo'];
101 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
103 $foo = $me->get('com.example.one', 'foo');
104 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
105 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
107 // later on, hook returns an extra managed entity ('bar')
108 $decls[] = $this->fixtures
['com.example.one-bar'];
109 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
111 $foo = $me->get('com.example.one', 'foo');
112 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
113 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
114 $bar = $me->get('com.example.one', 'bar');
115 $this->assertEquals('CRM_Example_One_Bar', $bar['name']);
116 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"');
118 // and then hook changes its mind, removing 'foo' (first of two entities)
120 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
122 $foo = $me->get('com.example.one', 'foo');
123 $this->assertTrue($foo === NULL);
124 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
125 $bar = $me->get('com.example.one', 'bar');
126 $this->assertEquals('CRM_Example_One_Bar', $bar['name']);
127 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"');
129 // and then hook changes its mind, removing 'bar' (the last remaining entity)
131 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
133 $foo = $me->get('com.example.one', 'foo');
134 $this->assertTrue($foo === NULL);
135 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
136 $bar = $me->get('com.example.one', 'bar');
137 $this->assertTrue($bar === NULL);
138 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"');
142 * Set up an active module with one managed-entity and, over
143 * time, the content of the entity changes
145 public function testModifyDeclaration_UpdateAlways() {
148 // create first managed entity ('foo')
149 $decls[] = $this->fixtures
['com.example.one-foo'];
150 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
152 $foo = $me->get('com.example.one', 'foo');
153 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
154 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
156 // later on, hook specification changes
157 $decls[0]['params']['class_name'] = 'CRM_Example_One_Foobar';
158 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
160 $foo2 = $me->get('com.example.one', 'foo');
161 $this->assertEquals('CRM_Example_One_Foobar', $foo2['name']);
162 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
163 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_FooBar"');
164 $this->assertEquals($foo['id'], $foo2['id']);
168 * Set up an active module with one managed-entity and, over
169 * time, the content of the entity changes
171 public function testModifyDeclaration_UpdateNever() {
174 // create first managed entity ('foo')
175 $decls[] = array_merge($this->fixtures
['com.example.one-foo'], array(
176 // Policy is to never update after initial creation
179 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
181 $foo = $me->get('com.example.one', 'foo');
182 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
183 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
185 // later on, hook specification changes
186 $decls[0]['params']['class_name'] = 'CRM_Example_One_Foobar';
187 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
189 $foo2 = $me->get('com.example.one', 'foo');
190 $this->assertEquals('CRM_Example_One_Foo', $foo2['name']);
191 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
192 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_FooBar"');
193 $this->assertEquals($foo['id'], $foo2['id']);
197 * Set up an active module with one managed-entity using the
198 * policy "cleanup=>never". When the managed-entity goes away,
199 * ensure that the policy is followed (ie the entity is not
202 public function testRemoveDeclaration_CleanupNever() {
205 // create first managed entity ('foo')
206 $decls[] = array_merge($this->fixtures
['com.example.one-foo'], array(
207 'cleanup' => 'never',
209 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
211 $foo = $me->get('com.example.one', 'foo');
212 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
213 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
215 // later on, entity definition disappears; but we decide not to do any cleanup (per policy)
217 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
219 $foo2 = $me->get('com.example.one', 'foo');
220 $this->assertEquals('CRM_Example_One_Foo', $foo2['name']);
221 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
222 $this->assertEquals($foo['id'], $foo2['id']);
226 * Set up an active module with one managed-entity using the
227 * policy "cleanup=>never". When the managed-entity goes away,
228 * ensure that the policy is followed (ie the entity is not
231 public function testRemoveDeclaration_CleanupUnused() {
234 // create first managed entity ('foo')
235 $decls[] = array_merge($this->fixtures
['com.example.one-foo'], array(
236 'cleanup' => 'unused',
238 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
240 $foo = $me->get('com.example.one', 'foo');
241 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
242 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
244 // Override 'getrefcount' ==> The refcount is 1
245 $this->adhocProvider
->addAction('getrefcount', 'access CiviCRM', function ($apiRequest) {
246 return civicrm_api3_create_success(array(
255 // Later on, entity definition disappears; but we decide not to do any cleanup (per policy)
257 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
259 $foo2 = $me->get('com.example.one', 'foo');
260 $this->assertEquals('CRM_Example_One_Foo', $foo2['name']);
261 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
262 $this->assertEquals($foo['id'], $foo2['id']);
264 // Override 'getrefcount' ==> The refcount is 0
265 $this->adhocProvider
->addAction('getrefcount', 'access CiviCRM', function ($apiRequest) {
266 return civicrm_api3_create_success(array());
269 // The entity definition disappeared and there's no reference; we decide to cleanup (per policy)
271 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
273 $foo3 = $me->get('com.example.one', 'foo');
274 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
275 $this->assertTrue($foo3 === NULL);
279 * Setup an active module with a malformed entity declaration.
281 public function testInvalidDeclarationModule() {
282 // create first managed entity ('foo')
286 'module' => 'com.example.unknown',
288 'entity' => 'CustomSearch',
291 'class_name' => 'CRM_Example_One_Foo',
295 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
298 $this->fail('Expected exception when using invalid declaration');
300 catch (Exception
$e) {
306 * Setup an active module with a malformed entity declaration.
308 public function testMissingName() {
309 // create first managed entity ('foo')
312 'module' => 'com.example.unknown',
315 'entity' => 'CustomSearch',
318 'class_name' => 'CRM_Example_One_Foo',
322 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
325 $this->fail('Expected exception when using invalid declaration');
327 catch (Exception
$e) {
333 * Setup an active module with a malformed entity declaration.
335 public function testMissingEntity() {
336 // create first managed entity ('foo')
339 'module' => 'com.example.unknown',
345 'class_name' => 'CRM_Example_One_Foo',
349 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
352 $this->fail('Expected exception when using invalid declaration');
354 catch (Exception
$e) {
360 * Setup an active module with an entity -- then disable and re-enable the
363 public function testDeactivateReactivateModule() {
364 // create first managed entity ('foo')
366 $decls[] = $this->fixtures
['com.example.one-foo'];
367 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
369 $foo = $me->get('com.example.one', 'foo');
370 $this->assertEquals(1, $foo['is_active']);
371 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
372 $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
374 // now deactivate module, which has empty decls and which cascades to managed object
375 $this->modules
['one']->is_active
= FALSE;
376 $me = new CRM_Core_ManagedEntities($this->modules
, array());
378 $foo = $me->get('com.example.one', 'foo');
379 $this->assertEquals(0, $foo['is_active']);
380 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
381 $this->assertDBQuery(0, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
383 // and reactivate module, which again provides decls and which cascades to managed object
384 $this->modules
['one']->is_active
= TRUE;
385 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
387 $foo = $me->get('com.example.one', 'foo');
388 $this->assertEquals(1, $foo['is_active']);
389 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
390 $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
394 * Setup an active module with an entity -- then entirely uninstall the
397 public function testUninstallModule() {
398 // create first managed entity ('foo')
400 $decls[] = $this->fixtures
['com.example.one-foo'];
401 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
403 $foo = $me->get('com.example.one', 'foo');
404 $this->assertEquals('CRM_Example_One_Foo', $foo['name']);
405 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
407 // then destroy module; note that decls go away
408 unset($this->modules
['one']);
409 $me = new CRM_Core_ManagedEntities($this->modules
, array());
411 $fooNew = $me->get('com.example.one', 'foo');
412 $this->assertTrue(NULL === $fooNew);
413 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"');
416 public function testDependentEntitiesUninstallCleanly() {
418 // Install a module with two dependent managed entities
420 $decls[] = $this->fixtures
['com.example.one-CustomGroup'];
421 $decls[] = $this->fixtures
['com.example.one-CustomField'];
422 $me = new CRM_Core_ManagedEntities($this->modules
, $decls);
425 // Uninstall the module
426 unset($this->modules
['one']);
427 $me = new CRM_Core_ManagedEntities($this->modules
, []);
430 // Ensure that no managed entities remain in the civicrm_managed
431 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_managed');
433 // Ensure that com.example.one-CustomGroup is deleted
434 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_custom_group WHERE name = "test_custom_group"');
436 // Ensure that com.example.one-CustomField is deleted
437 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_custom_field WHERE name = "test_custom_field"');