Skip to content

Commit 7ed7150

Browse files
committed
fix(modules): invoke lifecycle hooks once
1 parent f1df136 commit 7ed7150

2 files changed

Lines changed: 121 additions & 12 deletions

File tree

src/Core/Workers/Libs/WorkerModelsEvents/Actions/ReloadModuleStateAction.php

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,8 @@ public function handleModuleConfigChanges(ConfigClass $configClassObj, array $mo
191191
WorkerModelsEvents::invokeAction(ReloadManagerAction::class, [], 50);
192192
}
193193

194-
// Hook modules AFTER_ methods
195-
if (
196-
$moduleRecord['disabled'] === '1'
197-
&& method_exists($configClassObj, SystemConfigInterface::ON_AFTER_MODULE_DISABLE)
198-
) {
199-
call_user_func([$configClassObj, SystemConfigInterface::ON_AFTER_MODULE_DISABLE]);
200-
} elseif (
201-
$moduleRecord['disabled'] === '0'
202-
&& method_exists($configClassObj, SystemConfigInterface::ON_AFTER_MODULE_ENABLE)
203-
) {
204-
call_user_func([$configClassObj, SystemConfigInterface::ON_AFTER_MODULE_ENABLE]);
205-
}
194+
// Lifecycle hooks are owned by PbxExtensionState. The model event that
195+
// reaches this action is a consequence of that state transition, so
196+
// invoking AFTER hooks here would repeat module side effects.
206197
}
207198
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MikoPBX\Tests\Unit\Core\Workers\Libs\WorkerModelsEvents\Actions;
6+
7+
use MikoPBX\Core\Workers\Libs\WorkerModelsEvents\Actions\ReloadModuleStateAction;
8+
use MikoPBX\Modules\Config\ConfigClass;
9+
use PHPUnit\Framework\TestCase;
10+
use ReflectionClass;
11+
12+
/**
13+
* Ensures model-event processing reacts to persisted module state without
14+
* repeating lifecycle hooks already executed by PbxExtensionState.
15+
*/
16+
class ReloadModuleStateActionTest extends TestCase
17+
{
18+
public function testEnabledModelEventDoesNotInvokeAfterEnableHook(): void
19+
{
20+
$config = $this->makeConfig();
21+
22+
(new ReloadModuleStateAction())->handleModuleConfigChanges(
23+
$config,
24+
['disabled' => '0']
25+
);
26+
27+
$this->assertSame(0, $config->afterEnableCalls);
28+
$this->assertSame(0, $config->afterDisableCalls);
29+
}
30+
31+
public function testDisabledModelEventDoesNotInvokeAfterDisableHook(): void
32+
{
33+
$config = $this->makeConfig();
34+
35+
(new ReloadModuleStateAction())->handleModuleConfigChanges(
36+
$config,
37+
['disabled' => '1']
38+
);
39+
40+
$this->assertSame(0, $config->afterEnableCalls);
41+
$this->assertSame(0, $config->afterDisableCalls);
42+
}
43+
44+
public function testModelEventStillEvaluatesConfigurationReloadDeclarations(): void
45+
{
46+
$config = $this->makeConfig();
47+
48+
(new ReloadModuleStateAction())->handleModuleConfigChanges(
49+
$config,
50+
['disabled' => '0']
51+
);
52+
53+
$this->assertSame(1, $config->fail2BanCalls);
54+
$this->assertSame(1, $config->nginxLocationsCalls);
55+
$this->assertSame(1, $config->nginxServersCalls);
56+
$this->assertSame(1, $config->cronCalls);
57+
$this->assertSame(1, $config->managerCalls);
58+
}
59+
60+
private function makeConfig(): ModuleLifecycleConfigFixture
61+
{
62+
$reflection = new ReflectionClass(ModuleLifecycleConfigFixture::class);
63+
64+
/** @var ModuleLifecycleConfigFixture $config */
65+
$config = $reflection->newInstanceWithoutConstructor();
66+
return $config;
67+
}
68+
}
69+
70+
class ModuleLifecycleConfigFixture extends ConfigClass
71+
{
72+
public int $afterEnableCalls = 0;
73+
public int $afterDisableCalls = 0;
74+
public int $fail2BanCalls = 0;
75+
public int $nginxLocationsCalls = 0;
76+
public int $nginxServersCalls = 0;
77+
public int $cronCalls = 0;
78+
public int $managerCalls = 0;
79+
80+
public function onAfterModuleEnable(): void
81+
{
82+
$this->afterEnableCalls++;
83+
}
84+
85+
public function onAfterModuleDisable(): void
86+
{
87+
$this->afterDisableCalls++;
88+
}
89+
90+
public function generateFail2BanJails(): string
91+
{
92+
$this->fail2BanCalls++;
93+
return '';
94+
}
95+
96+
public function createNginxLocations(): string
97+
{
98+
$this->nginxLocationsCalls++;
99+
return '';
100+
}
101+
102+
public function createNginxServers(): string
103+
{
104+
$this->nginxServersCalls++;
105+
return '';
106+
}
107+
108+
public function createCronTasks(array &$tasks): void
109+
{
110+
$this->cronCalls++;
111+
}
112+
113+
public function generateManagerConf(): string
114+
{
115+
$this->managerCalls++;
116+
return '';
117+
}
118+
}

0 commit comments

Comments
 (0)