Skip to content

Commit bcc3cbd

Browse files
feat(install): dispatch InstallationCompletedEvent after setup completion
Add event dispatcher injection to Setup class and dispatch InstallationCompletedEvent with installation details (data directory, admin username, and admin email) after successful installation. Update SetupTest to mock the new IEventDispatcher dependency. Signed-off-by: Misha M.-Kupriyanov <[email protected]>
1 parent bc5945d commit bcc3cbd

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

lib/private/Setup.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
use OCP\AppFramework\Utility\ITimeFactory;
2424
use OCP\BackgroundJob\IJobList;
2525
use OCP\Defaults;
26+
use OCP\EventDispatcher\IEventDispatcher;
2627
use OCP\Http\Client\IClientService;
2728
use OCP\IAppConfig;
2829
use OCP\IConfig;
2930
use OCP\IGroup;
3031
use OCP\IGroupManager;
3132
use OCP\IL10N;
33+
use OCP\Install\Events\InstallationCompletedEvent;
3234
use OCP\IRequest;
3335
use OCP\IURLGenerator;
3436
use OCP\IUserManager;
@@ -51,6 +53,7 @@ public function __construct(
5153
protected LoggerInterface $logger,
5254
protected ISecureRandom $random,
5355
protected Installer $installer,
56+
protected IEventDispatcher $eventDispatcher,
5457
) {
5558
$this->l10n = $l10nFactory->get('lib');
5659
}
@@ -495,6 +498,13 @@ public function install(array $options, ?IOutput $output = null): array {
495498
}
496499
}
497500

501+
// Dispatch installation completed event
502+
$adminUsername = !$disableAdminUser ? ($options['adminlogin'] ?? null) : null;
503+
$adminEmail = !empty($options['adminemail']) ? $options['adminemail'] : null;
504+
$this->eventDispatcher->dispatchTyped(
505+
new InstallationCompletedEvent($dataDir, $adminUsername, $adminEmail)
506+
);
507+
498508
return $error;
499509
}
500510

tests/lib/SetupTest.php

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
use OC\Setup;
1414
use OC\SystemConfig;
1515
use OCP\Defaults;
16+
use OCP\EventDispatcher\IEventDispatcher;
1617
use OCP\IL10N;
18+
use OCP\Install\Events\InstallationCompletedEvent;
1719
use OCP\L10N\IFactory as IL10NFactory;
1820
use OCP\Security\ISecureRandom;
1921
use Psr\Log\LoggerInterface;
@@ -28,6 +30,7 @@ class SetupTest extends \Test\TestCase {
2830
protected LoggerInterface $logger;
2931
protected ISecureRandom $random;
3032
protected Installer $installer;
33+
protected IEventDispatcher $eventDispatcher;
3134

3235
protected function setUp(): void {
3336
parent::setUp();
@@ -42,9 +45,10 @@ protected function setUp(): void {
4245
$this->logger = $this->createMock(LoggerInterface::class);
4346
$this->random = $this->createMock(ISecureRandom::class);
4447
$this->installer = $this->createMock(Installer::class);
48+
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
4549
$this->setupClass = $this->getMockBuilder(Setup::class)
4650
->onlyMethods(['class_exists', 'is_callable', 'getAvailableDbDriversForPdo'])
47-
->setConstructorArgs([$this->config, $this->iniWrapper, $this->l10nFactory, $this->defaults, $this->logger, $this->random, $this->installer])
51+
->setConstructorArgs([$this->config, $this->iniWrapper, $this->l10nFactory, $this->defaults, $this->logger, $this->random, $this->installer, $this->eventDispatcher])
4852
->getMock();
4953
}
5054

@@ -170,4 +174,87 @@ public static function findWebRootProvider(): array {
170174
'empty' => ['', false],
171175
];
172176
}
177+
178+
/**
179+
* Test that Setup class has eventDispatcher injected
180+
*/
181+
public function testSetupHasEventDispatcher(): void {
182+
$reflectionClass = new \ReflectionClass($this->setupClass);
183+
$property = $reflectionClass->getProperty('eventDispatcher');
184+
$property->setAccessible(true);
185+
186+
$eventDispatcher = $property->getValue($this->setupClass);
187+
188+
$this->assertInstanceOf(IEventDispatcher::class, $eventDispatcher);
189+
}
190+
191+
/**
192+
* Helper method to extract event parameters from install options
193+
* This mirrors the logic in Setup::install() for extracting dataDir and admin parameters
194+
*
195+
* Note: This assumes 'directory' key is present in options. Setup::install() has a fallback
196+
* that sets a default directory if empty, but our tests always provide this key.
197+
*/
198+
private function extractInstallationEventParameters(array $options): array {
199+
$dataDir = htmlspecialchars_decode($options['directory']);
200+
$disableAdminUser = (bool)($options['admindisable'] ?? false);
201+
$adminUsername = !$disableAdminUser ? ($options['adminlogin'] ?? null) : null;
202+
$adminEmail = !empty($options['adminemail']) ? $options['adminemail'] : null;
203+
204+
return [$dataDir, $adminUsername, $adminEmail];
205+
}
206+
207+
/**
208+
* Test that InstallationCompletedEvent can be created with parameters from install options
209+
*
210+
* This test verifies that the InstallationCompletedEvent can be properly constructed with
211+
* the parameters that Setup::install() extracts from the options array for dataDir and admin parameters.
212+
*
213+
* Note: Testing that Setup::install() actually dispatches this event requires a full integration
214+
* test with database setup, file system operations, and app installation, which is beyond the
215+
* scope of a unit test. The event class itself is thoroughly tested in InstallationCompletedEventTest.php.
216+
*/
217+
public function testInstallationCompletedEventParametersFromInstallOptions(): void {
218+
// Simulate the options array as passed to Setup::install()
219+
$options = [
220+
'directory' => '/path/to/data',
221+
'adminlogin' => 'admin',
222+
'adminemail' => '[email protected]',
223+
];
224+
225+
// Extract parameters the same way Setup::install() does
226+
[$dataDir, $adminUsername, $adminEmail] = $this->extractInstallationEventParameters($options);
227+
228+
// Create the event as Setup::install() does after successful installation
229+
$event = new InstallationCompletedEvent($dataDir, $adminUsername, $adminEmail);
230+
231+
// Verify the event contains the expected values
232+
$this->assertEquals($dataDir, $event->getDataDirectory());
233+
$this->assertEquals($adminUsername, $event->getAdminUsername());
234+
$this->assertEquals($adminEmail, $event->getAdminEmail());
235+
$this->assertTrue($event->hasAdminUser());
236+
}
237+
238+
/**
239+
* Test that event parameters handle disabled admin user correctly
240+
*
241+
* This tests the scenario where Setup::install() is called with admindisable=true,
242+
* resulting in a null adminUsername in the event.
243+
*/
244+
public function testInstallationCompletedEventWithDisabledAdminUser(): void {
245+
$options = [
246+
'directory' => '/path/to/data',
247+
'admindisable' => true,
248+
];
249+
250+
// Extract parameters as Setup::install() does
251+
[$dataDir, $adminUsername, $adminEmail] = $this->extractInstallationEventParameters($options);
252+
253+
$event = new InstallationCompletedEvent($dataDir, $adminUsername, $adminEmail);
254+
255+
$this->assertEquals($dataDir, $event->getDataDirectory());
256+
$this->assertNull($event->getAdminUsername());
257+
$this->assertNull($event->getAdminEmail());
258+
$this->assertFalse($event->hasAdminUser());
259+
}
173260
}

0 commit comments

Comments
 (0)