Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  fix filesystem decoration preventing the Source optimization
  • Loading branch information
Baptouuuu committed Jun 17, 2020
2 parents 8dbcd7c + b473bdc commit b7c233e
Show file tree
Hide file tree
Showing 7 changed files with 488 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/OperatingSystem/Filesystem/Adapter.php
Expand Up @@ -78,7 +78,7 @@ private function wrap(FileInterface $file): FileInterface
return Directory::load(
$file,
$this->send,
$this->path->resolve(Path::of($file->name()->toString().'/')),
$this->path,
);
}

Expand Down
26 changes: 19 additions & 7 deletions src/OperatingSystem/Filesystem/Directory.php
Expand Up @@ -11,6 +11,8 @@
Directory as DirectoryInterface,
File as FileInterface,
Name,
Source,
Adapter,
};
use Innmind\Stream\Readable;
use Innmind\MediaType\MediaType;
Expand All @@ -20,7 +22,7 @@
Set,
};

final class Directory implements DirectoryInterface
final class Directory implements DirectoryInterface, Source
{
private DirectoryInterface $directory;
private SendActivity $send;
Expand All @@ -39,14 +41,24 @@ private function __construct(
public static function load(
DirectoryInterface $directory,
SendActivity $send,
Path $path
Path $parent
): self {
$path = $parent->resolve(Path::of($directory->name()->toString().'/'));
$self = new self($directory, $send, $path);
$send(new FileLoaded($path));

return $self;
}

public function sourcedAt(Adapter $adapter, Path $path): bool
{
if (!$this->directory instanceof Source) {
return false;
}

return $this->directory->sourcedAt($adapter, $path);
}

public function name(): Name
{
return $this->directory->name();
Expand All @@ -64,7 +76,7 @@ public function mediaType(): MediaType

public function add(FileInterface $file): DirectoryInterface
{
return new self(
return new UnsourcedDirectory(
$this->directory->add($file),
$this->send,
$this->path,
Expand All @@ -89,7 +101,7 @@ public function remove(Name $name): DirectoryInterface
return $this;
}

return new self(
return new UnsourcedDirectory(
$this->directory->remove($name),
$this->send,
$this->path,
Expand All @@ -98,7 +110,7 @@ public function remove(Name $name): DirectoryInterface

public function replaceAt(Path $path, FileInterface $file): DirectoryInterface
{
return new self(
return new UnsourcedDirectory(
$this->directory->replaceAt($path, $file),
$this->send,
$this->path,
Expand Down Expand Up @@ -139,10 +151,10 @@ public function modifications(): Sequence
private function wrap(FileInterface $file): FileInterface
{
if ($file instanceof DirectoryInterface) {
return new self(
return self::load(
$file,
$this->send,
$this->path->resolve(Path::of($file->name()->toString().'/')),
$this->path,
);
}

Expand Down
13 changes: 12 additions & 1 deletion src/OperatingSystem/Filesystem/File.php
Expand Up @@ -10,12 +10,14 @@
use Innmind\Filesystem\{
File as FileInterface,
Name,
Source,
Adapter,
};
use Innmind\Stream\Readable;
use Innmind\MediaType\MediaType;
use Innmind\Url\Path;

final class File implements FileInterface
final class File implements FileInterface, Source
{
private FileInterface $file;

Expand All @@ -28,6 +30,15 @@ public function __construct(
$send(new FileLoaded($folder->resolve(Path::of($file->name()->toString()))));
}

public function sourcedAt(Adapter $adapter, Path $path): bool
{
if (!$this->file instanceof Source) {
return false;
}

return $this->file->sourcedAt($adapter, $path);
}

public function name(): Name
{
return $this->file->name();
Expand Down
140 changes: 140 additions & 0 deletions src/OperatingSystem/Filesystem/UnsourcedDirectory.php
@@ -0,0 +1,140 @@
<?php
declare(strict_types = 1);

namespace Innmind\SilentCartographer\OperatingSystem\Filesystem;

use Innmind\SilentCartographer\{
SendActivity,
Room\Program\Activity\Filesystem\FileLoaded,
};
use Innmind\Filesystem\{
Directory as DirectoryInterface,
File as FileInterface,
Name,
};
use Innmind\Stream\Readable;
use Innmind\MediaType\MediaType;
use Innmind\Url\Path;
use Innmind\Immutable\{
Sequence,
Set,
};

final class UnsourcedDirectory implements DirectoryInterface
{
private DirectoryInterface $directory;
private SendActivity $send;
private Path $path;

public function __construct(
DirectoryInterface $directory,
SendActivity $send,
Path $path
) {
$this->directory = $directory;
$this->send = $send;
$this->path = $path;
}

public function name(): Name
{
return $this->directory->name();
}

public function content(): Readable
{
return $this->directory->content();
}

public function mediaType(): MediaType
{
return $this->directory->mediaType();
}

public function add(FileInterface $file): DirectoryInterface
{
return new self(
$this->directory->add($file),
$this->send,
$this->path,
);
}

public function get(Name $name): FileInterface
{
return $this->wrap($this->directory->get($name));
}

public function contains(Name $name): bool
{
return $this->directory->contains($name);
}

public function remove(Name $name): DirectoryInterface
{
$directory = $this->directory->remove($name);

if ($directory === $this->directory) {
return $this;
}

return new self(
$this->directory->remove($name),
$this->send,
$this->path,
);
}

public function replaceAt(Path $path, FileInterface $file): DirectoryInterface
{
return new self(
$this->directory->replaceAt($path, $file),
$this->send,
$this->path,
);
}

public function foreach(callable $function): void
{
$this->directory->foreach(function(FileInterface $file) use ($function): void {
$function($this->wrap($file));
});
}

public function filter(callable $predicate): Set
{
return $this->directory->filter(function(FileInterface $file) use ($predicate): bool {
return $predicate($this->wrap($file));
});
}

public function reduce($carry, callable $reducer)
{
/** @psalm-suppress MissingClosureParamType */
return $this->directory->reduce(
$carry,
function($carry, FileInterface $file) use ($reducer) {
/** @psalm-suppress MixedArgument */
return $reducer($carry, $this->wrap($file));
},
);
}

public function modifications(): Sequence
{
return $this->directory->modifications();
}

private function wrap(FileInterface $file): FileInterface
{
if ($file instanceof DirectoryInterface) {
return Directory::load(
$file,
$this->send,
$this->path,
);
}

return new File($file, $this->send, $this->path);
}
}
66 changes: 62 additions & 4 deletions tests/OperatingSystem/Filesystem/DirectoryTest.php
Expand Up @@ -5,10 +5,16 @@

use Innmind\SilentCartographer\{
OperatingSystem\Filesystem\Directory,
OperatingSystem\Filesystem\UnsourcedDirectory,
OperatingSystem\Filesystem\File as DecoratedFile,
SendActivity,
Room\Program\Activity\Filesystem\FileLoaded,
};
use Innmind\Filesystem\{
Adapter,
Source,
Directory as DirectoryInterface,
};
use Innmind\Url\Path as RealPath;
use PHPUnit\Framework\TestCase;
use Innmind\BlackBox\{
Expand Down Expand Up @@ -43,6 +49,58 @@ public function testHoldProperties()
});
}

public function testAlwaysReturnFalseWhenCheckingSourceOfUnknownDirectoryOrigin()
{
$this
->forAll(
Fixture::any(),
Path::any(),
Path::directories(),
)
->then(function($inner, $path, $parent) {
$directory = Directory::load(
$inner,
$this->createMock(SendActivity::class),
$parent,
);

$this->assertFalse($directory->sourcedAt(
$this->createMock(Adapter::class),
$path,
));
});
}

public function testSourcedAt()
{
$this
->forAll(
Fixture::any(),
Path::any(),
Path::any(),
Path::directories(),
)
->then(function($inner, $pathA, $pathB, $parent) {
$adapter = $this->createMock(Adapter::class);
$directory = Directory::load(
new DirectoryInterface\Source(
$inner,
$adapter,
$pathA,
),
$this->createMock(SendActivity::class),
$parent,
);

$this->assertTrue($directory->sourcedAt($adapter, $pathA));
$this->assertFalse($directory->sourcedAt($adapter, $pathB));
$this->assertFalse($directory->sourcedAt(
$this->createMock(Adapter::class),
$pathA,
));
});
}

public function testSendActivityWhenLoadingDirectory()
{
$this
Expand All @@ -55,8 +113,8 @@ public function testSendActivityWhenLoadingDirectory()
$send
->expects($this->once())
->method('__invoke')
->with($this->callback(function(FileLoaded $activity) use ($path) {
return $activity->path() === $path;
->with($this->callback(function(FileLoaded $activity) use ($path, $inner) {
return $activity->path()->toString() === $path->toString().$inner->name()->toString().'/';
}));

Directory::load($inner, $send, $path);
Expand Down Expand Up @@ -98,7 +156,7 @@ public function testAddingFileDoesntSendActivity()
->method('__invoke');

$directory = Directory::load($inner, $send, $path)->add($file);
$this->assertInstanceOf(Directory::class, $directory);
$this->assertInstanceOf(UnsourcedDirectory::class, $directory);
});
}

Expand All @@ -120,7 +178,7 @@ public function testReplaceAtConserveDecoration()
$file,
);

$this->assertInstanceOf(Directory::class, $directory);
$this->assertInstanceOf(UnsourcedDirectory::class, $directory);
});
}

Expand Down

0 comments on commit b7c233e

Please sign in to comment.