Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | ||
aba1cd8b EM |
3 | /** |
4 | * Class CRM_Core_ManagedEntitiesTest | |
acb109b7 | 5 | * @group headless |
aba1cd8b | 6 | */ |
6a488035 | 7 | class CRM_Core_ManagedEntitiesTest extends CiviUnitTestCase { |
378e2654 TO |
8 | /** |
9 | * @var \Civi\API\Kernel | |
10 | */ | |
11 | protected $apiKernel; | |
12 | ||
13 | /** | |
14 | * @var \Civi\API\Provider\AdhocProvider | |
15 | */ | |
16 | protected $adhocProvider; | |
17 | ||
aba1cd8b | 18 | /** |
bbf66e9c | 19 | * @var array(string $shortName => CRM_Core_Module $module) |
aba1cd8b | 20 | */ |
bbf66e9c TO |
21 | protected $modules; |
22 | ||
6ea13979 TO |
23 | protected $fixtures; |
24 | ||
00be9182 | 25 | public function setUp() { |
e4ccda28 | 26 | $this->useTransaction(TRUE); |
6a488035 TO |
27 | parent::setUp(); |
28 | $this->modules = array( | |
29 | 'one' => new CRM_Core_Module('com.example.one', TRUE), | |
30 | 'two' => new CRM_Core_Module('com.example.two', TRUE), | |
31 | ); | |
e4ccda28 TO |
32 | |
33 | // Testing on drupal-demo fails because some extensions have mgd ents. | |
34 | CRM_Core_DAO::singleValueQuery('DELETE FROM civicrm_managed'); | |
6ea13979 TO |
35 | |
36 | $this->fixtures['com.example.one-foo'] = array( | |
37 | 'module' => 'com.example.one', | |
38 | 'name' => 'foo', | |
39 | 'entity' => 'CustomSearch', | |
40 | 'params' => array( | |
41 | 'version' => 3, | |
42 | 'class_name' => 'CRM_Example_One_Foo', | |
43 | 'is_reserved' => 1, | |
44 | ), | |
45 | ); | |
46 | $this->fixtures['com.example.one-bar'] = array( | |
47 | 'module' => 'com.example.one', | |
48 | 'name' => 'bar', | |
49 | 'entity' => 'CustomSearch', | |
50 | 'params' => array( | |
51 | 'version' => 3, | |
52 | 'class_name' => 'CRM_Example_One_Bar', | |
53 | 'is_reserved' => 1, | |
54 | ), | |
55 | ); | |
378e2654 | 56 | |
048222df | 57 | $this->apiKernel = \Civi::service('civi_api_kernel'); |
378e2654 TO |
58 | $this->adhocProvider = new \Civi\API\Provider\AdhocProvider(3, 'CustomSearch'); |
59 | $this->apiKernel->registerApiProvider($this->adhocProvider); | |
6a488035 TO |
60 | } |
61 | ||
00be9182 | 62 | public function tearDown() { |
6a488035 | 63 | parent::tearDown(); |
048222df | 64 | \Civi::reset(); |
6a488035 TO |
65 | } |
66 | ||
67 | /** | |
68 | * Set up an active module and, over time, the hook implementation changes | |
69 | * to (1) create 'foo' entity, (2) create 'bar' entity', (3) remove 'foo' | |
70 | * entity | |
71 | */ | |
00be9182 | 72 | public function testAddRemoveEntitiesModule_UpdateAlways_DeleteAlways() { |
6a488035 TO |
73 | $decls = array(); |
74 | ||
75 | // create first managed entity ('foo') | |
6ea13979 | 76 | $decls[] = $this->fixtures['com.example.one-foo']; |
6a488035 TO |
77 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); |
78 | $me->reconcile(); | |
79 | $foo = $me->get('com.example.one', 'foo'); | |
80 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
81 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
82 | ||
83 | // later on, hook returns an extra managed entity ('bar') | |
6ea13979 | 84 | $decls[] = $this->fixtures['com.example.one-bar']; |
6a488035 TO |
85 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); |
86 | $me->reconcile(); | |
87 | $foo = $me->get('com.example.one', 'foo'); | |
88 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
89 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
90 | $bar = $me->get('com.example.one', 'bar'); | |
91 | $this->assertEquals('CRM_Example_One_Bar', $bar['name']); | |
92 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"'); | |
93 | ||
94 | // and then hook changes its mind, removing 'foo' (first of two entities) | |
95 | unset($decls[0]); | |
96 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
97 | $me->reconcile(); | |
98 | $foo = $me->get('com.example.one', 'foo'); | |
99 | $this->assertTrue($foo === NULL); | |
100 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
101 | $bar = $me->get('com.example.one', 'bar'); | |
102 | $this->assertEquals('CRM_Example_One_Bar', $bar['name']); | |
103 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"'); | |
104 | ||
105 | // and then hook changes its mind, removing 'bar' (the last remaining entity) | |
106 | unset($decls[1]); | |
107 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
108 | $me->reconcile(); | |
109 | $foo = $me->get('com.example.one', 'foo'); | |
110 | $this->assertTrue($foo === NULL); | |
111 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
112 | $bar = $me->get('com.example.one', 'bar'); | |
113 | $this->assertTrue($bar === NULL); | |
114 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Bar"'); | |
115 | } | |
116 | ||
117 | /** | |
118 | * Set up an active module with one managed-entity and, over | |
119 | * time, the content of the entity changes | |
120 | */ | |
00be9182 | 121 | public function testModifyDeclaration_UpdateAlways() { |
6a488035 TO |
122 | $decls = array(); |
123 | ||
124 | // create first managed entity ('foo') | |
6ea13979 | 125 | $decls[] = $this->fixtures['com.example.one-foo']; |
6a488035 TO |
126 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); |
127 | $me->reconcile(); | |
128 | $foo = $me->get('com.example.one', 'foo'); | |
129 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
130 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
131 | ||
132 | // later on, hook specification changes | |
133 | $decls[0]['params']['class_name'] = 'CRM_Example_One_Foobar'; | |
134 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
135 | $me->reconcile(); | |
136 | $foo2 = $me->get('com.example.one', 'foo'); | |
137 | $this->assertEquals('CRM_Example_One_Foobar', $foo2['name']); | |
138 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
139 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_FooBar"'); | |
140 | $this->assertEquals($foo['id'], $foo2['id']); | |
141 | } | |
142 | ||
0dd54586 TO |
143 | /** |
144 | * Set up an active module with one managed-entity and, over | |
145 | * time, the content of the entity changes | |
146 | */ | |
00be9182 | 147 | public function testModifyDeclaration_UpdateNever() { |
0dd54586 TO |
148 | $decls = array(); |
149 | ||
150 | // create first managed entity ('foo') | |
151 | $decls[] = array_merge($this->fixtures['com.example.one-foo'], array( | |
152 | 'update' => 'never', // Policy is to never update after initial creation | |
153 | )); | |
154 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
155 | $me->reconcile(); | |
156 | $foo = $me->get('com.example.one', 'foo'); | |
157 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
158 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
159 | ||
160 | // later on, hook specification changes | |
161 | $decls[0]['params']['class_name'] = 'CRM_Example_One_Foobar'; | |
162 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
163 | $me->reconcile(); | |
164 | $foo2 = $me->get('com.example.one', 'foo'); | |
165 | $this->assertEquals('CRM_Example_One_Foo', $foo2['name']); | |
166 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
167 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_FooBar"'); | |
168 | $this->assertEquals($foo['id'], $foo2['id']); | |
169 | } | |
170 | ||
1f103dc4 TO |
171 | /** |
172 | * Set up an active module with one managed-entity using the | |
173 | * policy "cleanup=>never". When the managed-entity goes away, | |
174 | * ensure that the policy is followed (ie the entity is not | |
175 | * deleted). | |
176 | */ | |
00be9182 | 177 | public function testRemoveDeclaration_CleanupNever() { |
1f103dc4 TO |
178 | $decls = array(); |
179 | ||
180 | // create first managed entity ('foo') | |
181 | $decls[] = array_merge($this->fixtures['com.example.one-foo'], array( | |
21dfd5f5 | 182 | 'cleanup' => 'never', |
1f103dc4 TO |
183 | )); |
184 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
185 | $me->reconcile(); | |
186 | $foo = $me->get('com.example.one', 'foo'); | |
187 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
188 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
189 | ||
190 | // later on, entity definition disappears; but we decide not to do any cleanup (per policy) | |
191 | $decls = array(); | |
192 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
193 | $me->reconcile(); | |
194 | $foo2 = $me->get('com.example.one', 'foo'); | |
195 | $this->assertEquals('CRM_Example_One_Foo', $foo2['name']); | |
196 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
197 | $this->assertEquals($foo['id'], $foo2['id']); | |
198 | } | |
199 | ||
378e2654 TO |
200 | /** |
201 | * Set up an active module with one managed-entity using the | |
202 | * policy "cleanup=>never". When the managed-entity goes away, | |
203 | * ensure that the policy is followed (ie the entity is not | |
204 | * deleted). | |
205 | */ | |
00be9182 | 206 | public function testRemoveDeclaration_CleanupUnused() { |
378e2654 TO |
207 | $decls = array(); |
208 | ||
209 | // create first managed entity ('foo') | |
210 | $decls[] = array_merge($this->fixtures['com.example.one-foo'], array( | |
21dfd5f5 | 211 | 'cleanup' => 'unused', |
378e2654 TO |
212 | )); |
213 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
214 | $me->reconcile(); | |
215 | $foo = $me->get('com.example.one', 'foo'); | |
216 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
217 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
218 | ||
219 | // Override 'getrefcount' ==> The refcount is 1 | |
92915c55 | 220 | $this->adhocProvider->addAction('getrefcount', 'access CiviCRM', function ($apiRequest) { |
378e2654 TO |
221 | return civicrm_api3_create_success(array( |
222 | array( | |
223 | 'name' => 'mock', | |
224 | 'type' => 'mock', | |
225 | 'count' => 1, | |
21dfd5f5 | 226 | ), |
378e2654 TO |
227 | )); |
228 | }); | |
229 | ||
230 | // Later on, entity definition disappears; but we decide not to do any cleanup (per policy) | |
231 | $decls = array(); | |
232 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
233 | $me->reconcile(); | |
234 | $foo2 = $me->get('com.example.one', 'foo'); | |
235 | $this->assertEquals('CRM_Example_One_Foo', $foo2['name']); | |
236 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
237 | $this->assertEquals($foo['id'], $foo2['id']); | |
238 | ||
378e2654 | 239 | // Override 'getrefcount' ==> The refcount is 0 |
92915c55 | 240 | $this->adhocProvider->addAction('getrefcount', 'access CiviCRM', function ($apiRequest) { |
378e2654 TO |
241 | return civicrm_api3_create_success(array()); |
242 | }); | |
243 | ||
244 | // The entity definition disappeared and there's no reference; we decide to cleanup (per policy) | |
245 | $decls = array(); | |
246 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
247 | $me->reconcile(); | |
248 | $foo3 = $me->get('com.example.one', 'foo'); | |
249 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
250 | $this->assertTrue($foo3 === NULL); | |
251 | } | |
252 | ||
6a488035 | 253 | /** |
eceb18cc | 254 | * Setup an active module with a malformed entity declaration. |
6a488035 | 255 | */ |
00be9182 | 256 | public function testInvalidDeclarationModule() { |
6a488035 TO |
257 | // create first managed entity ('foo') |
258 | $decls = array(); | |
259 | $decls[] = array( | |
260 | 'module' => 'com.example.unknown', // erroneous | |
261 | 'name' => 'foo', | |
262 | 'entity' => 'CustomSearch', | |
263 | 'params' => array( | |
264 | 'version' => 3, | |
265 | 'class_name' => 'CRM_Example_One_Foo', | |
266 | 'is_reserved' => 1, | |
267 | ), | |
268 | ); | |
269 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
270 | try { | |
271 | $me->reconcile(); | |
272 | $this->fail('Expected exception when using invalid declaration'); | |
0db6c3e1 TO |
273 | } |
274 | catch (Exception $e) { | |
6c6e6187 | 275 | // good |
6a488035 TO |
276 | } |
277 | } | |
278 | ||
279 | /** | |
eceb18cc | 280 | * Setup an active module with a malformed entity declaration. |
6a488035 | 281 | */ |
00be9182 | 282 | public function testMissingName() { |
6a488035 TO |
283 | // create first managed entity ('foo') |
284 | $decls = array(); | |
285 | $decls[] = array( | |
286 | 'module' => 'com.example.unknown', | |
287 | 'name' => NULL, // erroneous | |
288 | 'entity' => 'CustomSearch', | |
289 | 'params' => array( | |
290 | 'version' => 3, | |
291 | 'class_name' => 'CRM_Example_One_Foo', | |
292 | 'is_reserved' => 1, | |
293 | ), | |
294 | ); | |
295 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
296 | try { | |
297 | $me->reconcile(); | |
298 | $this->fail('Expected exception when using invalid declaration'); | |
0db6c3e1 TO |
299 | } |
300 | catch (Exception $e) { | |
6c6e6187 | 301 | // good |
6a488035 TO |
302 | } |
303 | } | |
304 | ||
305 | /** | |
eceb18cc | 306 | * Setup an active module with a malformed entity declaration. |
6a488035 | 307 | */ |
00be9182 | 308 | public function testMissingEntity() { |
6a488035 TO |
309 | // create first managed entity ('foo') |
310 | $decls = array(); | |
311 | $decls[] = array( | |
312 | 'module' => 'com.example.unknown', | |
313 | 'name' => 'foo', | |
314 | 'entity' => NULL, // erroneous | |
315 | 'params' => array( | |
316 | 'version' => 3, | |
317 | 'class_name' => 'CRM_Example_One_Foo', | |
318 | 'is_reserved' => 1, | |
319 | ), | |
320 | ); | |
321 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
322 | try { | |
323 | $me->reconcile(); | |
324 | $this->fail('Expected exception when using invalid declaration'); | |
0db6c3e1 TO |
325 | } |
326 | catch (Exception $e) { | |
6c6e6187 | 327 | // good |
6a488035 TO |
328 | } |
329 | } | |
330 | ||
331 | /** | |
332 | * Setup an active module with an entity -- then disable and re-enable the | |
333 | * module | |
334 | */ | |
00be9182 | 335 | public function testDeactivateReactivateModule() { |
6a488035 TO |
336 | // create first managed entity ('foo') |
337 | $decls = array(); | |
6ea13979 | 338 | $decls[] = $this->fixtures['com.example.one-foo']; |
6a488035 TO |
339 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); |
340 | $me->reconcile(); | |
341 | $foo = $me->get('com.example.one', 'foo'); | |
342 | $this->assertEquals(1, $foo['is_active']); | |
343 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
344 | $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
345 | ||
346 | // now deactivate module, which has empty decls and which cascades to managed object | |
347 | $this->modules['one']->is_active = FALSE; | |
348 | $me = new CRM_Core_ManagedEntities($this->modules, array()); | |
349 | $me->reconcile(); | |
350 | $foo = $me->get('com.example.one', 'foo'); | |
351 | $this->assertEquals(0, $foo['is_active']); | |
352 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
353 | $this->assertDBQuery(0, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
354 | ||
355 | // and reactivate module, which again provides decls and which cascades to managed object | |
356 | $this->modules['one']->is_active = TRUE; | |
357 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); | |
358 | $me->reconcile(); | |
359 | $foo = $me->get('com.example.one', 'foo'); | |
360 | $this->assertEquals(1, $foo['is_active']); | |
361 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
362 | $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
363 | } | |
364 | ||
365 | /** | |
366 | * Setup an active module with an entity -- then entirely uninstall the | |
367 | * module | |
368 | */ | |
00be9182 | 369 | public function testUninstallModule() { |
6a488035 TO |
370 | // create first managed entity ('foo') |
371 | $decls = array(); | |
6ea13979 | 372 | $decls[] = $this->fixtures['com.example.one-foo']; |
6a488035 TO |
373 | $me = new CRM_Core_ManagedEntities($this->modules, $decls); |
374 | $me->reconcile(); | |
375 | $foo = $me->get('com.example.one', 'foo'); | |
376 | $this->assertEquals('CRM_Example_One_Foo', $foo['name']); | |
377 | $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
378 | ||
e4f46be0 | 379 | // then destroy module; note that decls go away |
6a488035 TO |
380 | unset($this->modules['one']); |
381 | $me = new CRM_Core_ManagedEntities($this->modules, array()); | |
382 | $me->reconcile(); | |
383 | $fooNew = $me->get('com.example.one', 'foo'); | |
384 | $this->assertTrue(NULL === $fooNew); | |
385 | $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); | |
386 | } | |
96025800 | 387 | |
6a488035 | 388 | } |