Merge pull request #7722 from kcristiano/17593
[civicrm-core.git] / tests / phpunit / CRM / Extension / Manager / ModuleTest.php
1 <?php
2
3 /**
4 * Class CRM_Extension_Manager_ModuleTest
5 */
6 class CRM_Extension_Manager_ModuleTest extends CiviUnitTestCase {
7
8 public function setUp() {
9 parent::setUp();
10 // $query = "INSERT INTO civicrm_domain ( name, version ) VALUES ( 'domain', 3 )";
11 // $result = CRM_Core_DAO::executeQuery($query);
12 global $_test_extension_manager_moduletest_counts;
13 $_test_extension_manager_moduletest_counts = array();
14 $this->basedir = $this->createTempDir('ext-');
15 $this->system = new CRM_Extension_System(array(
16 'extensionsDir' => $this->basedir,
17 'extensionsURL' => 'http://testbase/',
18 ));
19 $this->setExtensionSystem($this->system);
20 }
21
22 public function tearDown() {
23 parent::tearDown();
24 $this->system = NULL;
25 }
26
27 /**
28 * Install an extension with a valid type name.
29 */
30 public function testInstallDisableUninstall() {
31 $manager = $this->system->getManager();
32 $this->assertModuleActiveByName(FALSE, 'moduletest');
33
34 $manager->install(array('test.extension.manager.moduletest'));
35 $this->assertHookCounts('moduletest', array(
36 'install' => 1,
37 'postInstall' => 1,
38 'enable' => 1,
39 'disable' => 0,
40 'uninstall' => 0,
41 ));
42 $this->assertModuleActiveByName(TRUE, 'moduletest');
43 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
44
45 $manager->disable(array('test.extension.manager.moduletest'));
46 $this->assertHookCounts('moduletest', array(
47 'install' => 1,
48 'postInstall' => 1,
49 'enable' => 1,
50 'disable' => 1,
51 'uninstall' => 0,
52 ));
53 $this->assertModuleActiveByName(FALSE, 'moduletest');
54 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
55
56 $manager->uninstall(array('test.extension.manager.moduletest'));
57 $this->assertHookCounts('moduletest', array(
58 'install' => 1,
59 'postInstall' => 1,
60 'enable' => 1,
61 'disable' => 1,
62 'uninstall' => 1,
63 ));
64 $this->assertModuleActiveByName(FALSE, 'moduletest');
65 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
66 }
67
68 /**
69 * Install an extension with a valid type name.
70 */
71 public function testInstallDisableEnable() {
72 $manager = $this->system->getManager();
73 $this->assertModuleActiveByName(FALSE, 'moduletest');
74 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
75
76 $manager->install(array('test.extension.manager.moduletest'));
77 $this->assertHookCounts('moduletest', array(
78 'install' => 1,
79 'enable' => 1,
80 'disable' => 0,
81 'uninstall' => 0,
82 ));
83 $this->assertModuleActiveByName(TRUE, 'moduletest');
84 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
85
86 $manager->disable(array('test.extension.manager.moduletest'));
87 $this->assertHookCounts('moduletest', array(
88 'install' => 1,
89 'enable' => 1,
90 'disable' => 1,
91 'uninstall' => 0,
92 ));
93 $this->assertModuleActiveByName(FALSE, 'moduletest');
94 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
95
96 $manager->enable(array('test.extension.manager.moduletest'));
97 $this->assertHookCounts('moduletest', array(
98 'install' => 1,
99 'enable' => 2,
100 'disable' => 1,
101 'uninstall' => 0,
102 ));
103 $this->assertModuleActiveByName(TRUE, 'moduletest');
104 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
105 }
106
107 /**
108 * Install an extension then forcibly remove the code and cleanup DB afterwards.
109 */
110 public function testInstall_DirtyRemove_Disable_Uninstall() {
111 // create temporary extension (which can dirtily remove later)
112 $this->_createExtension('test.extension.manager.module.auto1', 'module', 'test_extension_manager_module_auto1');
113 $mainfile = $this->basedir . '/test.extension.manager.module.auto1/test_extension_manager_module_auto1.php';
114 $this->assertTrue(file_exists($mainfile));
115 $manager = $this->system->getManager();
116 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
117 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto1');
118
119 // install it
120 $manager->install(array('test.extension.manager.module.auto1'));
121 $this->assertEquals('installed', $manager->getStatus('test.extension.manager.module.auto1'));
122 $this->assertHookCounts('test_extension_manager_module_auto1', array(
123 'install' => 1,
124 'enable' => 1,
125 'disable' => 0,
126 'uninstall' => 0,
127 ));
128 $this->assertModuleActiveByName(TRUE, 'test_extension_manager_module_auto1');
129 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.module.auto1');
130
131 // dirty removal
132 CRM_Utils_File::cleanDir($this->basedir . '/test.extension.manager.module.auto1', TRUE, FALSE);
133 $manager->refresh();
134 $this->assertEquals('installed-missing', $manager->getStatus('test.extension.manager.module.auto1'));
135
136 // disable while missing
137 $manager->disable(array('test.extension.manager.module.auto1'));
138 $this->assertEquals('disabled-missing', $manager->getStatus('test.extension.manager.module.auto1'));
139 $this->assertHookCounts('test_extension_manager_module_auto1', array(
140 'install' => 1,
141 'enable' => 1,
142 'disable' => 0, // normally called -- but not for missing modules!
143 'uninstall' => 0,
144 ));
145 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
146 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
147
148 $manager->uninstall(array('test.extension.manager.module.auto1'));
149 $this->assertHookCounts('test_extension_manager_module_auto1', array(
150 'install' => 1,
151 'enable' => 1,
152 'disable' => 0, // normally called -- but not for missing modules!
153 'uninstall' => 0, // normally called -- but not for missing modules!
154 ));
155 $this->assertEquals('unknown', $manager->getStatus('test.extension.manager.module.auto1'));
156 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
157 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto1');
158 }
159
160 /**
161 * Install an extension then forcibly remove the code and cleanup DB afterwards.
162 */
163 public function testInstall_DirtyRemove_Disable_Restore() {
164 // create temporary extension (which can dirtily remove later)
165 $this->_createExtension('test.extension.manager.module.auto2', 'module', 'test_extension_manager_module_auto2');
166 $mainfile = $this->basedir . '/test.extension.manager.module.auto2/test_extension_manager_module_auto2.php';
167 $this->assertTrue(file_exists($mainfile));
168 $manager = $this->system->getManager();
169 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
170 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto2');
171
172 // install it
173 $manager->install(array('test.extension.manager.module.auto2'));
174 $this->assertEquals('installed', $manager->getStatus('test.extension.manager.module.auto2'));
175 $this->assertHookCounts('test_extension_manager_module_auto2', array(
176 'install' => 1,
177 'enable' => 1,
178 'disable' => 0,
179 'uninstall' => 0,
180 ));
181 $this->assertModuleActiveByName(TRUE, 'test_extension_manager_module_auto2');
182 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.module.auto2');
183
184 // dirty removal
185 CRM_Utils_File::cleanDir($this->basedir . '/test.extension.manager.module.auto2', TRUE, FALSE);
186 $manager->refresh();
187 $this->assertEquals('installed-missing', $manager->getStatus('test.extension.manager.module.auto2'));
188
189 // disable while missing
190 $manager->disable(array('test.extension.manager.module.auto2'));
191 $this->assertEquals('disabled-missing', $manager->getStatus('test.extension.manager.module.auto2'));
192 $this->assertHookCounts('test_extension_manager_module_auto2', array(
193 'install' => 1,
194 'enable' => 1,
195 'disable' => 0, // normally called -- but not for missing modules!
196 'uninstall' => 0,
197 ));
198 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
199 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
200
201 // restore the code
202 $this->_createExtension('test.extension.manager.module.auto2', 'module', 'test_extension_manager_module_auto2');
203 $manager->refresh();
204 $this->assertHookCounts('test_extension_manager_module_auto2', array(
205 'install' => 1,
206 'enable' => 1,
207 'disable' => 0,
208 'uninstall' => 0,
209 ));
210 $this->assertEquals('disabled', $manager->getStatus('test.extension.manager.module.auto2'));
211 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
212 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto2');
213 }
214
215 /**
216 * @param $module
217 * @param array $counts
218 * Expected hook invocation counts ($hookName => $count).
219 */
220 public function assertHookCounts($module, $counts) {
221 global $_test_extension_manager_moduletest_counts;
222 foreach ($counts as $key => $expected) {
223 $actual = @$_test_extension_manager_moduletest_counts[$module][$key];
224 $this->assertEquals($expected, $actual,
225 sprintf('Expected %d call(s) to hook_civicrm_%s -- found %d', $expected, $key, $actual)
226 );
227 }
228 }
229
230 /**
231 * @param $expectedIsActive
232 * @param $prefix
233 */
234 public function assertModuleActiveByName($expectedIsActive, $prefix) {
235 $activeModules = CRM_Core_PseudoConstant::getModuleExtensions(TRUE); // FIXME
236 foreach ($activeModules as $activeModule) {
237 if ($activeModule['prefix'] == $prefix) {
238 $this->assertEquals($expectedIsActive, TRUE);
239 return;
240 }
241 }
242 $this->assertEquals($expectedIsActive, FALSE);
243 }
244
245 /**
246 * @param $expectedIsActive
247 * @param $key
248 */
249 public function assertModuleActiveByKey($expectedIsActive, $key) {
250 foreach (CRM_Core_Module::getAll() as $module) {
251 if ($module->name == $key) {
252 $this->assertEquals((bool) $expectedIsActive, (bool) $module->is_active);
253 return;
254 }
255 }
256 $this->assertEquals($expectedIsActive, FALSE);
257 }
258
259 /**
260 * @param $key
261 * @param $type
262 * @param $file
263 * @param string $template
264 */
265 public function _createExtension($key, $type, $file, $template = self::MODULE_TEMPLATE) {
266 $basedir = $this->basedir;
267 mkdir("$basedir/$key");
268 file_put_contents("$basedir/$key/info.xml", "<extension key='$key' type='$type'><file>$file</file></extension>");
269 file_put_contents("$basedir/$key/$file.php", strtr($template, array('_FILE_' => $file)));
270 $this->system->getCache()->flush();
271 $this->system->getManager()->refresh();
272 }
273
274 /**
275 * @param $module
276 * @param string $name
277 */
278 public static function incHookCount($module, $name) {
279 global $_test_extension_manager_moduletest_counts;
280 if (!isset($_test_extension_manager_moduletest_counts[$module][$name])) {
281 $_test_extension_manager_moduletest_counts[$module][$name] = 0;
282 }
283 $_test_extension_manager_moduletest_counts[$module][$name] = 1 + (int) $_test_extension_manager_moduletest_counts[$module][$name];
284 }
285
286 const MODULE_TEMPLATE = "
287 <?php
288 function _FILE__civicrm_install() {
289 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'install');
290 }
291
292 function _FILE__civicrm_postInstall() {
293 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'postInstall');
294 }
295
296 function _FILE__civicrm_uninstall() {
297 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'uninstall');
298 }
299
300 function _FILE__civicrm_enable() {
301 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'enable');
302 }
303
304 function _FILE__civicrm_disable() {
305 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'disable');
306 }
307 ";
308
309 }