Remove unused skipRedirect param
[civicrm-core.git] / tests / phpunit / CRM / Extension / ManagerTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 /**
29 * Class CRM_Extension_ManagerTest
30 * @group headless
31 */
32 class CRM_Extension_ManagerTest extends CiviUnitTestCase {
33 const TESTING_TYPE = 'report';
34 const OTHER_TESTING_TYPE = 'module';
35
36 public function setUp() {
37 parent::setUp();
38 list ($this->basedir, $this->container) = $this->_createContainer();
39 $this->mapper = new CRM_Extension_Mapper($this->container);
40 }
41
42 public function tearDown() {
43 parent::tearDown();
44 }
45
46 /**
47 * Install an extension with an invalid type name.
48 *
49 * @expectedException CRM_Extension_Exception
50 */
51 public function testInstallInvalidType() {
52 $mockFunction = $this->mockMethod;
53 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
54 $testingTypeManager->expects($this->never())
55 ->method('onPreInstall');
56 $manager = $this->_createManager([
57 self::OTHER_TESTING_TYPE => $testingTypeManager,
58 ]);
59 $manager->install(['test.foo.bar']);
60 }
61
62 /**
63 * Install an extension with a valid type name.
64 *
65 * Note: We initially install two extensions but then toggle only
66 * the second. This controls for bad SQL queries which hit either
67 * "the first row" or "all rows".
68 */
69 public function testInstall_Disable_Uninstall() {
70 $mockFunction = $this->mockMethod;
71 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
72 $manager = $this->_createManager([
73 self::TESTING_TYPE => $testingTypeManager,
74 ]);
75 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
76 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
77
78 $testingTypeManager
79 ->expects($this->exactly(2))
80 ->method('onPreInstall');
81 $testingTypeManager
82 ->expects($this->exactly(2))
83 ->method('onPostInstall');
84 $manager->install(['test.whiz.bang', 'test.foo.bar']);
85 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
86 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
87
88 $testingTypeManager
89 ->expects($this->once())
90 ->method('onPreDisable');
91 $testingTypeManager
92 ->expects($this->once())
93 ->method('onPostDisable');
94 $manager->disable(['test.foo.bar']);
95 $this->assertEquals('disabled', $manager->getStatus('test.foo.bar'));
96 // no side-effect
97 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
98
99 $testingTypeManager
100 ->expects($this->once())
101 ->method('onPreUninstall');
102 $testingTypeManager
103 ->expects($this->once())
104 ->method('onPostUninstall');
105 $manager->uninstall(['test.foo.bar']);
106 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
107 // no side-effect
108 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
109 }
110
111 /**
112 * This is the same as testInstall_Disable_Uninstall, but we also install and remove a dependency.
113 *
114 * @throws \CRM_Extension_Exception
115 */
116 public function test_InstallAuto_DisableDownstream_UninstallDownstream() {
117 $mockFunction = $this->mockMethod;
118 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
119 $manager = $this->_createManager([
120 self::TESTING_TYPE => $testingTypeManager,
121 ]);
122 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
123 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.downstream'));
124 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
125
126 $testingTypeManager->expects($this->exactly(2))->method('onPreInstall');
127 $testingTypeManager->expects($this->exactly(2))->method('onPostInstall');
128 $this->assertEquals(['test.foo.bar', 'test.foo.downstream'],
129 $manager->findInstallRequirements(['test.foo.downstream']));
130 $manager->install(
131 $manager->findInstallRequirements(['test.foo.downstream']));
132 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
133 $this->assertEquals('installed', $manager->getStatus('test.foo.downstream'));
134 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
135
136 $testingTypeManager->expects($this->once())->method('onPreDisable');
137 $testingTypeManager->expects($this->once())->method('onPostDisable');
138 $this->assertEquals(['test.foo.downstream'],
139 $manager->findDisableRequirements(['test.foo.downstream']));
140 $manager->disable(['test.foo.downstream']);
141 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
142 $this->assertEquals('disabled', $manager->getStatus('test.foo.downstream'));
143 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
144
145 $testingTypeManager->expects($this->once())->method('onPreUninstall');
146 $testingTypeManager->expects($this->once())->method('onPostUninstall');
147 $manager->uninstall(['test.foo.downstream']);
148 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
149 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.downstream'));
150 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
151 }
152
153 /**
154 * This is the same as testInstallAuto_Twice
155 *
156 * @throws \CRM_Extension_Exception
157 */
158 public function testInstallAuto_Twice() {
159 $mockFunction = $this->mockMethod;
160 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
161 $manager = $this->_createManager([
162 self::TESTING_TYPE => $testingTypeManager,
163 ]);
164 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
165 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.downstream'));
166 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
167
168 $testingTypeManager->expects($this->exactly(2))->method('onPreInstall');
169 $testingTypeManager->expects($this->exactly(2))->method('onPostInstall');
170 $this->assertEquals(['test.foo.bar', 'test.foo.downstream'],
171 $manager->findInstallRequirements(['test.foo.downstream']));
172 $manager->install(
173 $manager->findInstallRequirements(['test.foo.downstream']));
174 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
175 $this->assertEquals('installed', $manager->getStatus('test.foo.downstream'));
176 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
177
178 // And install a second time...
179 $testingTypeManager->expects($this->exactly(0))->method('onPreInstall');
180 $testingTypeManager->expects($this->exactly(0))->method('onPostInstall');
181 $manager->install(
182 $manager->findInstallRequirements(['test.foo.downstream']));
183 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
184 $this->assertEquals('installed', $manager->getStatus('test.foo.downstream'));
185 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
186 }
187
188 public function test_InstallAuto_DisableUpstream() {
189 $mockFunction = $this->mockMethod;
190 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
191 $manager = $this->_createManager([
192 self::TESTING_TYPE => $testingTypeManager,
193 ]);
194 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
195 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.downstream'));
196 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
197
198 $testingTypeManager->expects($this->exactly(2))->method('onPreInstall');
199 $testingTypeManager->expects($this->exactly(2))->method('onPostInstall');
200 $this->assertEquals(['test.foo.bar', 'test.foo.downstream'],
201 $manager->findInstallRequirements(['test.foo.downstream']));
202 $manager->install(
203 $manager->findInstallRequirements(['test.foo.downstream']));
204 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
205 $this->assertEquals('installed', $manager->getStatus('test.foo.downstream'));
206 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
207
208 $testingTypeManager->expects($this->never())->method('onPreDisable');
209 $testingTypeManager->expects($this->never())->method('onPostDisable');
210 $this->assertEquals(['test.foo.downstream', 'test.foo.bar'],
211 $manager->findDisableRequirements(['test.foo.bar']));
212
213 try {
214 $manager->disable(['test.foo.bar']);
215 $this->fail('Expected disable to fail due to dependency');
216 }
217 catch (CRM_Extension_Exception $e) {
218 $this->assertRegExp('/test.foo.downstream/', $e->getMessage());
219 }
220
221 // Status unchanged
222 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
223 $this->assertEquals('installed', $manager->getStatus('test.foo.downstream'));
224 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
225 }
226
227 /**
228 * Install an extension and then harshly remove the underlying source.
229 * Subseuently disable and uninstall.
230 */
231 public function testInstall_DirtyRemove_Disable_Uninstall() {
232 $mockFunction = $this->mockMethod;
233 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
234 $manager = $this->_createManager([
235 self::TESTING_TYPE => $testingTypeManager,
236 ]);
237 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
238
239 $manager->install(['test.foo.bar']);
240 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
241
242 $this->assertTrue(file_exists("{$this->basedir}/weird/foobar/info.xml"));
243 CRM_Utils_File::cleanDir("{$this->basedir}/weird/foobar", TRUE, FALSE);
244 $this->assertFalse(file_exists("{$this->basedir}/weird/foobar/info.xml"));
245 $manager->refresh();
246 $this->assertEquals('installed-missing', $manager->getStatus('test.foo.bar'));
247
248 $testingTypeManager
249 ->expects($this->once())
250 ->method('onPreDisable');
251 $testingTypeManager
252 ->expects($this->once())
253 ->method('onPostDisable');
254 $manager->disable(['test.foo.bar']);
255 $this->assertEquals('disabled-missing', $manager->getStatus('test.foo.bar'));
256
257 $testingTypeManager
258 ->expects($this->once())
259 ->method('onPreUninstall');
260 $testingTypeManager
261 ->expects($this->once())
262 ->method('onPostUninstall');
263 $manager->uninstall(['test.foo.bar']);
264 $this->assertEquals('unknown', $manager->getStatus('test.foo.bar'));
265 }
266
267 /**
268 * Install an extension with a valid type name.
269 */
270 public function testInstall_Disable_Enable() {
271 $mockFunction = $this->mockMethod;
272 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
273 $manager = $this->_createManager([
274 self::TESTING_TYPE => $testingTypeManager,
275 ]);
276 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
277 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
278
279 $testingTypeManager
280 ->expects($this->exactly(2))
281 ->method('onPreInstall');
282 $testingTypeManager
283 ->expects($this->exactly(2))
284 ->method('onPostInstall');
285 $manager->install(['test.whiz.bang', 'test.foo.bar']);
286 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
287 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
288
289 $testingTypeManager
290 ->expects($this->once())
291 ->method('onPreDisable');
292 $testingTypeManager
293 ->expects($this->once())
294 ->method('onPostDisable');
295 $manager->disable(['test.foo.bar']);
296 $this->assertEquals('disabled', $manager->getStatus('test.foo.bar'));
297 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
298
299 $testingTypeManager
300 ->expects($this->once())
301 ->method('onPreEnable');
302 $testingTypeManager
303 ->expects($this->once())
304 ->method('onPostEnable');
305 $manager->enable(['test.foo.bar']);
306 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
307 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
308 }
309
310 /**
311 * Performing 'install' on a 'disabled' extension performs an 'enable'
312 */
313 public function testInstall_Disable_Install() {
314 $mockFunction = $this->mockMethod;
315 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
316 $manager = $this->_createManager([
317 self::TESTING_TYPE => $testingTypeManager,
318 ]);
319 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
320
321 $testingTypeManager
322 ->expects($this->once())
323 ->method('onPreInstall');
324 $testingTypeManager
325 ->expects($this->once())
326 ->method('onPostInstall');
327 $manager->install(['test.foo.bar']);
328 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
329
330 $testingTypeManager
331 ->expects($this->once())
332 ->method('onPreDisable');
333 $testingTypeManager
334 ->expects($this->once())
335 ->method('onPostDisable');
336 $manager->disable(['test.foo.bar']);
337 $this->assertEquals('disabled', $manager->getStatus('test.foo.bar'));
338
339 $testingTypeManager
340 ->expects($this->once())
341 ->method('onPreEnable');
342 $testingTypeManager
343 ->expects($this->once())
344 ->method('onPostEnable');
345 // install() instead of enable()
346 $manager->install(['test.foo.bar']);
347 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
348 }
349
350 /**
351 * Install an extension with a valid type name.
352 */
353 public function testEnableBare() {
354 $mockFunction = $this->mockMethod;
355 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
356 $manager = $this->_createManager([
357 self::TESTING_TYPE => $testingTypeManager,
358 ]);
359 $this->assertEquals('uninstalled', $manager->getStatus('test.foo.bar'));
360
361 $testingTypeManager
362 ->expects($this->once())
363 ->method('onPreInstall');
364 $testingTypeManager
365 ->expects($this->once())
366 ->method('onPostInstall');
367 $testingTypeManager
368 ->expects($this->never())
369 ->method('onPreEnable');
370 $testingTypeManager
371 ->expects($this->never())
372 ->method('onPostEnable');
373 // enable not install
374 $manager->enable(['test.foo.bar']);
375 $this->assertEquals('installed', $manager->getStatus('test.foo.bar'));
376 }
377
378 /**
379 * Get the status of an unknown extension.
380 */
381 public function testStatusUnknownKey() {
382 $mockFunction = $this->mockMethod;
383 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
384 $testingTypeManager->expects($this->never())
385 ->method('onPreInstall');
386 $manager = $this->_createManager([
387 self::TESTING_TYPE => $testingTypeManager,
388 ]);
389 $this->assertEquals('unknown', $manager->getStatus('test.foo.bar.whiz.bang'));
390 }
391
392 /**
393 * Replace code for an extension that doesn't exist in the container
394 */
395 public function testReplace_Unknown() {
396 $mockFunction = $this->mockMethod;
397 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
398 $manager = $this->_createManager([
399 self::TESTING_TYPE => $testingTypeManager,
400 ]);
401 $this->assertEquals('unknown', $manager->getStatus('test.newextension'));
402
403 $this->download = $this->_createDownload('test.newextension', 'newextension');
404
405 $testingTypeManager
406 // no data to replace
407 ->expects($this->never())
408 ->method('onPreReplace');
409 $testingTypeManager
410 // no data to replace
411 ->expects($this->never())
412 ->method('onPostReplace');
413 $manager->replace($this->download);
414 $this->assertEquals('uninstalled', $manager->getStatus('test.newextension'));
415 $this->assertTrue(file_exists("{$this->basedir}/test.newextension/info.xml"));
416 $this->assertTrue(file_exists("{$this->basedir}/test.newextension/newextension.php"));
417 $this->assertEquals(self::TESTING_TYPE, $this->mapper->keyToInfo('test.newextension')->type);
418 $this->assertEquals('newextension', $this->mapper->keyToInfo('test.newextension')->file);
419 }
420
421 /**
422 * Replace code for an extension that doesn't exist in the container
423 */
424 public function testReplace_Uninstalled() {
425 $mockFunction = $this->mockMethod;
426 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
427 $manager = $this->_createManager([
428 self::TESTING_TYPE => $testingTypeManager,
429 ]);
430 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
431 $this->assertEquals('oddball', $this->mapper->keyToInfo('test.whiz.bang')->file);
432
433 $this->download = $this->_createDownload('test.whiz.bang', 'newextension');
434
435 $testingTypeManager
436 // no data to replace
437 ->expects($this->never())
438 ->method('onPreReplace');
439 $testingTypeManager
440 // no data to replace
441 ->expects($this->never())
442 ->method('onPostReplace');
443 $manager->replace($this->download);
444 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
445 $this->assertTrue(file_exists("{$this->basedir}/weird/whizbang/info.xml"));
446 $this->assertTrue(file_exists("{$this->basedir}/weird/whizbang/newextension.php"));
447 $this->assertFalse(file_exists("{$this->basedir}/weird/whizbang/oddball.php"));
448 $this->assertEquals(self::TESTING_TYPE, $this->mapper->keyToInfo('test.whiz.bang')->type);
449 $this->assertEquals('newextension', $this->mapper->keyToInfo('test.whiz.bang')->file);
450 }
451
452 /**
453 * Install a module and then replace it with new code.
454 *
455 * Note that some metadata changes between versions -- the original has
456 * file="oddball", and the upgrade has file="newextension".
457 */
458 public function testReplace_Installed() {
459 $mockFunction = $this->mockMethod;
460 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
461 $manager = $this->_createManager([
462 self::TESTING_TYPE => $testingTypeManager,
463 ]);
464 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
465 $this->assertEquals('oddball', $this->mapper->keyToInfo('test.whiz.bang')->file);
466
467 $manager->install(['test.whiz.bang']);
468 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
469 $this->assertEquals('oddball', $this->mapper->keyToInfo('test.whiz.bang')->file);
470 $this->assertDBQuery('oddball', 'SELECT file FROM civicrm_extension WHERE full_name ="test.whiz.bang"');
471
472 $this->download = $this->_createDownload('test.whiz.bang', 'newextension');
473
474 $testingTypeManager
475 ->expects($this->once())
476 ->method('onPreReplace');
477 $testingTypeManager
478 ->expects($this->once())
479 ->method('onPostReplace');
480 $manager->replace($this->download);
481 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
482 $this->assertTrue(file_exists("{$this->basedir}/weird/whizbang/info.xml"));
483 $this->assertTrue(file_exists("{$this->basedir}/weird/whizbang/newextension.php"));
484 $this->assertFalse(file_exists("{$this->basedir}/weird/whizbang/oddball.php"));
485 $this->assertEquals('newextension', $this->mapper->keyToInfo('test.whiz.bang')->file);
486 $this->assertDBQuery('newextension', 'SELECT file FROM civicrm_extension WHERE full_name ="test.whiz.bang"');
487 }
488
489 /**
490 * Install a module and then delete (leaving stale DB info); restore
491 * the module by downloading new code.
492 *
493 * Note that some metadata changes between versions -- the original has
494 * file="oddball", and the upgrade has file="newextension".
495 */
496 public function testReplace_InstalledMissing() {
497 $mockFunction = $this->mockMethod;
498 $testingTypeManager = $this->$mockFunction('CRM_Extension_Manager_Interface');
499 $manager = $this->_createManager([
500 self::TESTING_TYPE => $testingTypeManager,
501 ]);
502
503 // initial installation
504 $this->assertEquals('uninstalled', $manager->getStatus('test.whiz.bang'));
505 $manager->install(['test.whiz.bang']);
506 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
507
508 // dirty remove
509 $this->assertTrue(file_exists("{$this->basedir}/weird/whizbang/info.xml"));
510 CRM_Utils_File::cleanDir("{$this->basedir}/weird/whizbang", TRUE, FALSE);
511 $this->assertFalse(file_exists("{$this->basedir}/weird/whizbang/info.xml"));
512 $manager->refresh();
513 $this->assertEquals('installed-missing', $manager->getStatus('test.whiz.bang'));
514
515 // download and reinstall
516 $this->download = $this->_createDownload('test.whiz.bang', 'newextension');
517
518 $testingTypeManager
519 ->expects($this->once())
520 ->method('onPreReplace');
521 $testingTypeManager
522 ->expects($this->once())
523 ->method('onPostReplace');
524 $manager->replace($this->download);
525 $this->assertEquals('installed', $manager->getStatus('test.whiz.bang'));
526 $this->assertTrue(file_exists("{$this->basedir}/test.whiz.bang/info.xml"));
527 $this->assertTrue(file_exists("{$this->basedir}/test.whiz.bang/newextension.php"));
528 $this->assertEquals('newextension', $this->mapper->keyToInfo('test.whiz.bang')->file);
529 $this->assertDBQuery('newextension', 'SELECT file FROM civicrm_extension WHERE full_name ="test.whiz.bang"');
530 }
531
532 /**
533 * @param $typeManagers
534 *
535 * @return CRM_Extension_Manager
536 */
537 public function _createManager($typeManagers) {
538 //list ($basedir, $c) = $this->_createContainer();
539 $mapper = new CRM_Extension_Mapper($this->container);
540 return new CRM_Extension_Manager($this->container, $this->container, $this->mapper, $typeManagers);
541 }
542
543 /**
544 * @param CRM_Utils_Cache_Interface $cache
545 * @param null $cacheKey
546 *
547 * @return array
548 */
549 public function _createContainer(CRM_Utils_Cache_Interface $cache = NULL, $cacheKey = NULL) {
550 $basedir = $this->createTempDir('ext-');
551 mkdir("$basedir/weird");
552 mkdir("$basedir/weird/foobar");
553 file_put_contents("$basedir/weird/foobar/info.xml", "<extension key='test.foo.bar' type='" . self::TESTING_TYPE . "'><file>oddball</file></extension>");
554 // not needed for now // file_put_contents("$basedir/weird/bar/oddball.php", "<?php\n");
555 mkdir("$basedir/weird/whizbang");
556 file_put_contents("$basedir/weird/whizbang/info.xml", "<extension key='test.whiz.bang' type='" . self::TESTING_TYPE . "'><file>oddball</file></extension>");
557 // not needed for now // file_put_contents("$basedir/weird/whizbang/oddball.php", "<?php\n");
558 mkdir("$basedir/weird/downstream");
559 file_put_contents("$basedir/weird/downstream/info.xml", "<extension key='test.foo.downstream' type='" . self::TESTING_TYPE . "'><file>oddball</file><requires><ext>test.foo.bar</ext></requires></extension>");
560 // not needed for now // file_put_contents("$basedir/weird/downstream/oddball.php", "<?php\n");
561 $c = new CRM_Extension_Container_Basic($basedir, 'http://example/basedir', $cache, $cacheKey);
562 return [$basedir, $c];
563 }
564
565 /**
566 * @param $key
567 * @param $file
568 *
569 * @return string
570 */
571 public function _createDownload($key, $file) {
572 $basedir = $this->createTempDir('ext-dl-');
573 file_put_contents("$basedir/info.xml", "<extension key='$key' type='" . self::TESTING_TYPE . "'><file>$file</file></extension>");
574 file_put_contents("$basedir/$file.php", "<?php\n");
575 return $basedir;
576 }
577
578 }