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