19declare(strict_types=1);
23use PHPUnit\Framework\MockObject\MockObject;
40 protected function setUp(): void
44 if (!defined(
'SYSTEM_USER_ID')) {
45 define(
'SYSTEM_USER_ID', 6);
48 $this->tmp_dir = sys_get_temp_dir() .
'/mail-migration-unit-' . uniqid(
'',
true);
49 mkdir($this->tmp_dir .
'/mail', 0775,
true);
55 $io = $this->createStub(AdminInteraction::class);
56 $io->method(
'inform')->willReturnCallback(
function (
string $message):
void {
66 ? $this->createMock(ilDBInterface::class)
67 : $this->createStub(ilDBInterface::class);
68 $db->method(
'quote')->willReturnCallback(
static fn(mixed $value):
string =>
"'" . $value .
"'");
69 $db->method(
'supportsTransactions')->willReturn(
true);
78 assert(
$db instanceof MockObject);
88 'moveFilesOfPathToCollection',
90 'getCollectionBuilder',
95 $helper = $this->getMockBuilder(ilResourceStorageMigrationHelper::class)
96 ->disableOriginalConstructor()
97 ->onlyMethods($methods)
100 $helper = $this->getStubBuilder(ilResourceStorageMigrationHelper::class)
101 ->disableOriginalConstructor()
102 ->onlyMethods($methods)
106 $helper->method(
'getClientDataDir')->willReturn($this->tmp_dir);
115 new ReflectionClass($this->migration)->getProperty(
'helper')->setValue($this->migration,
$helper);
116 assert(
$helper instanceof MockObject);
125 $reflection = new ReflectionClass($this->migration);
126 $reflection->getProperty(
'helper')->setValue($this->migration,
$helper);
127 $reflection->getProperty(
'io')->setValue($this->migration, $io);
132 exec(
'chmod -R u+rwx ' . escapeshellarg($this->tmp_dir) .
' && rm -rf ' . escapeshellarg($this->tmp_dir));
151 $db = $this->useDatabaseMock();
152 $db->expects($this->once())->method(
'setLimit')->with(25);
153 $db->method(
'query')->willReturnCallback(
155 $captured_sql = $sql;
157 return $this->createStub(ilDBStatement::class);
160 $db->method(
'fetchAssoc')->willReturnOnConsecutiveCalls([
'path' =>
'newest'], [
'path' =>
'older'],
null);
162 $paths = $this->invokePrivate(
'nextUnmigratedPaths', []);
164 $this->assertSame([
'newest',
'older'], $paths);
165 $this->assertStringContainsString(
'ORDER BY MAX(m.send_time) DESC', $captured_sql);
166 $this->assertStringNotContainsString(
'LIMIT', $captured_sql);
175 $db = $this->useDatabaseMock();
176 $db->expects($this->once())->method(
'setLimit')->with(50);
177 $db->method(
'query')->willReturnCallback(
179 $captured_sql = $sql;
181 return $this->createStub(ilDBStatement::class);
184 $db->method(
'fetchAssoc')->willReturn(
null);
186 $this->invokePrivate(
'migrateSerializedMailAttachments', []);
188 $this->assertStringContainsString(
'LEFT JOIN mail_attachment ma ON ma.mail_id = m.mail_id', $captured_sql);
189 $this->assertStringContainsString(
'WHERE ma.mail_id IS NULL', $captured_sql);
190 $this->assertStringContainsString(
'LEFT JOIN mail_obj_data fo ON fo.obj_id = m.folder_id', $captured_sql);
191 $this->assertStringContainsString(
'ORDER BY m.send_time DESC, m.mail_id DESC', $captured_sql);
196 $dir = $this->createDirectory(
'6_100', [
'a.pdf' =>
'1234']);
197 $helper = $this->useHelperMock();
198 $this->db->method(
'query')->willReturn($this->createStub(ilDBStatement::class));
199 $this->db->method(
'queryF')->willReturn($this->createStub(ilDBStatement::class));
200 $this->db->method(
'in')->willReturn(
'mail_id IN (1,2)');
201 $this->db->method(
'fetchAssoc')->willReturnOnConsecutiveCalls(
213 $collection = $this->createMock(ResourceCollection::class);
214 $collection->expects($this->once())->method(
'add')->with($resource_id);
215 $collection->method(
'count')->willReturn(1);
216 $collection->method(
'getIdentification')->willReturn($rcid);
217 $collection->method(
'getResourceIdentifications')->willReturn([$resource_id]);
218 $collection_builder = $this->createMock(CollectionBuilder::class);
219 $collection_builder->expects($this->once())->method(
'new')->with(6)->willReturn($collection);
220 $collection_builder->expects($this->once())->method(
'store')->with($collection)->willReturn(
true);
221 $collection_builder->expects($this->once())->method(
'get')->with($rcid)->willReturn($collection);
222 $helper->method(
'getCollectionBuilder')->willReturn($collection_builder);
223 $this->expectConfidential($resource_id);
224 $helper->expects($this->once())
225 ->method(
'movePathToStorage')
226 ->willReturnCallback(
function (
230 Closure $revision_title,
233 $this->assertSame($dir .
'/a.pdf', $path);
234 $this->assertSame(6, $owner);
235 $this->assertNull($file_name);
236 $this->assertSame(md5(
'a.pdf'), $revision_title(
'a.pdf'));
237 $this->assertTrue($copy);
242 $this->db->method(
'manipulateF')->willReturnCallback(
243 function (
string $sql, array $types, array $values) use (&$statements):
int {
244 $statements[] = [$sql, $values];
249 $this->invokePrivate(
'migrateSentAttachmentDirectories', []);
251 $this->assertSame([
'UPDATE mail_attachment SET rcid = %s WHERE path = %s', [
'dir-rcid',
'6_100']], $statements[0]);
252 $this->assertSame([
'UPDATE mail SET attachments = %s WHERE mail_id IN (1,2)', [
'dir-rcid']], $statements[1]);
253 $this->assertDirectoryDoesNotExist($dir);
258 $dir = $this->createDirectory(
'6_100', [
'a.pdf' =>
'1234',
'b.pdf' =>
'5678']);
259 $helper = $this->useHelperMock();
260 $db = $this->useDatabaseMock();
261 $db->method(
'query')->willReturn($this->createStub(ilDBStatement::class));
262 $db->method(
'queryF')->willReturn($this->createStub(ilDBStatement::class));
263 $db->method(
'fetchAssoc')->willReturnOnConsecutiveCalls(
268 $db->expects($this->never())->method(
'manipulateF');
269 $collection = $this->createStub(ResourceCollection::class);
270 $collection_builder = $this->createMock(CollectionBuilder::class);
271 $collection_builder->method(
'new')->willReturn($collection);
272 $collection_builder->expects($this->never())->method(
'store');
273 $helper->method(
'getCollectionBuilder')->willReturn($collection_builder);
275 $helper->expects($this->exactly(2))
276 ->method(
'movePathToStorage')
283 $helper->method(
'getStakeholder')->willReturn($stakeholder);
284 $manager = $this->createMock(Manager::class);
285 $manager->expects($this->once())->method(
'remove')->with(
289 $helper->method(
'getManager')->willReturn($manager);
291 $this->invokePrivate(
'migrateSentAttachmentDirectories', []);
293 $this->assertFileExists($dir .
'/a.pdf');
294 $this->assertFileExists($dir .
'/b.pdf');
295 $this->assertReported(
'WARNING',
'not every file could be stored');
300 $db = $this->useDatabaseMock();
301 $helper = $this->useHelperMock();
302 $db->method(
'query')->willReturn($this->createStub(ilDBStatement::class));
303 $db->method(
'queryF')->willReturn($this->createStub(ilDBStatement::class));
304 $db->method(
'fetchAssoc')->willReturnOnConsecutiveCalls(
310 $helper->expects($this->never())->method(
'movePathToStorage');
311 $db->expects($this->once())->method(
'manipulateF')->with(
312 'UPDATE mail_attachment SET rcid = %s WHERE path = %s',
317 $this->invokePrivate(
'migrateSentAttachmentDirectories', []);
319 $this->assertReported(
'WARNING',
'does not exist');
324 file_put_contents($this->tmp_dir .
'/mail/6_Übung 1.pdf',
'%PDF');
325 $helper = $this->useHelperMock();
326 $collection = $this->createMock(ResourceCollection::class);
327 $collection->expects($this->once())->method(
'add');
328 $collection->method(
'count')->willReturn(1);
330 $collection_builder = $this->createStub(CollectionBuilder::class);
331 $collection_builder->method(
'new')->willReturn($collection);
332 $collection_builder->method(
'store')->willReturn(
true);
333 $helper->method(
'getCollectionBuilder')->willReturn($collection_builder);
334 $helper->expects($this->once())
335 ->method(
'movePathToStorage')
336 ->willReturnCallback(
function (
340 Closure $revision_title,
343 $this->assertSame(
'Übung 1.pdf', $file_name());
344 $this->assertSame(md5(
'Übung 1.pdf'), $revision_title());
345 $this->assertTrue($copy,
'Pool files are copied, they stay in the pool');
351 $rcid = $this->invokePrivate(
352 'migratePoolFilenamesToCollection',
353 [[
'Übung 1.pdf',
'gone.pdf'], 6, $this->tmp_dir .
'/mail', 42]
356 $this->assertSame(
'draft-rcid', $rcid->serialize());
357 $this->assertFileExists($this->tmp_dir .
'/mail/6_Übung 1.pdf');
358 $this->assertReported(
'WARNING',
'gone.pdf');
363 file_put_contents($this->tmp_dir .
'/mail/6_exists.pdf',
'%PDF');
364 $db = $this->useDatabaseMock();
365 $collection = $this->createStub(ResourceCollection::class);
366 $collection->method(
'count')->willReturn(1);
368 $collection_builder = $this->createStub(CollectionBuilder::class);
369 $collection_builder->method(
'new')->willReturn($collection);
370 $collection_builder->method(
'store')->willReturn(
true);
371 $this->helper->method(
'getCollectionBuilder')->willReturn($collection_builder);
374 $db->expects($this->once())->method(
'manipulateF')->with(
375 'INSERT INTO mail_attachment (mail_id, path, rcid) VALUES (%s, %s, %s)',
377 [42,
'',
'draft-rcid']
379 $db->expects($this->once())->method(
'update')->with(
385 $this->invokePrivate(
'migrateSerializedMail', [42, 6, serialize([
'exists.pdf']), $this->tmp_dir .
'/mail',
true]);
390 file_put_contents($this->tmp_dir .
'/mail/6_exists.pdf',
'%PDF');
391 $helper = $this->useHelperMock();
392 $helper->expects($this->never())->method(
'movePathToStorage');
393 $db = $this->useDatabaseMock();
394 $db->expects($this->never())->method(
'manipulateF');
395 $db->expects($this->once())->method(
'update')->with(
401 $this->invokePrivate(
'migrateSerializedMail', [44, 6, serialize([
'exists.pdf']), $this->tmp_dir .
'/mail',
false]);
403 $this->assertFileExists($this->tmp_dir .
'/mail/6_exists.pdf');
404 $this->assertReported(
'WARNING',
'outside drafts and outbox');
409 $db = $this->useDatabaseMock();
410 $db->expects($this->once())->method(
'update')->with(
416 $this->invokePrivate(
'migrateSerializedMail', [43, 6,
'a:1:{broken', $this->tmp_dir .
'/mail',
true]);
418 $this->assertReported(
'WARNING',
'could not be read');
427 $this->db->method(
'query')->willThrowException(
new RuntimeException(
'MySQL server has gone away'));
430 $this->migration->step($this->createStub(Environment::class));
431 $this->fail(
'The exception must be rethrown');
432 }
catch (RuntimeException
$e) {
433 $this->assertSame(
'MySQL server has gone away',
$e->getMessage());
436 $this->assertReported(
'ERROR',
'MySQL server has gone away');
446 $this->db->method(
'queryF')->willReturn($this->createStub(ilDBStatement::class));
447 $this->db->method(
'fetchAssoc')->willReturnOnConsecutiveCalls([
'sender_id' => 42], [
'sender_id' => 0]);
449 $this->assertSame(42, $this->invokePrivate(
'resolveOwnerIdForPath', [
'6_1']));
450 $this->assertSame(
SYSTEM_USER_ID, $this->invokePrivate(
'resolveOwnerIdForPath', [
'6_2']));
460 $dir = $this->tmp_dir .
'/mail/' . $relative_path;
461 mkdir($dir, 0775,
true);
462 foreach (
$files as $name => $content) {
463 file_put_contents($dir .
'/' . $name, $content);
471 $manager = $this->createMock(Manager::class);
472 $manager->expects($this->once())->method(
'setConfidential')->with($identification,
true);
473 $this->helper->method(
'getManager')->willReturn($manager);
478 foreach ($this->messages as
$message) {
480 $this->assertMatchesRegularExpression(
'/^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]/',
$message);
486 $this->fail(sprintf(
'No %s containing "%s" reported, got: %s', $level, $needle, implode(
"\n", $this->messages)));
494 return new ReflectionClass($this->migration)->getMethod($method)->invoke($this->migration, ...
$arguments);
Class ResourceCollection.
Class ResourceCollectionIdentification.
Class ResourceIdentification.
Class ilResourceStorageMigrationHelper.
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
This defines ways in which objectives may interact with admins during the setup.
An environment holds resources to be used in the setup process.