Compare commits

..

4 Commits

Author SHA1 Message Date
Philipp Lang 18650ba7ad Add merge 2023-11-29 23:01:01 +01:00
Philipp Lang 8654d13e81 Add full body assertion 2023-11-29 23:00:47 +01:00
Philipp Lang 5a5f1756e1 Set uuid string for temporary filename 2023-11-29 13:03:37 +01:00
Philipp Lang 6d88ccb8f1 Add full string assertion for Document 2023-11-29 12:05:56 +01:00
3 changed files with 70 additions and 18 deletions

View File

@ -10,7 +10,14 @@ use Log;
abstract class BaseCompiler implements Responsable abstract class BaseCompiler implements Responsable
{ {
protected File $file; public function __construct(protected ?File $file = null)
{
}
public static function fromFile(string $file): static
{
return new static(new File($file, false));
}
public function compile(Document $document): self public function compile(Document $document): self
{ {
@ -21,7 +28,7 @@ abstract class BaseCompiler implements Responsable
if ($document->template()) { if ($document->template()) {
$templatePath = $document->template()->fullPath(); $templatePath = $document->template()->fullPath();
exec('rsync -av '.escapeshellarg($templatePath).'/ '.escapeshellarg($this->file->getPath())); exec('rsync -av ' . escapeshellarg($templatePath) . '/ ' . escapeshellarg($this->file->getPath()));
} }
exec($this->command($document), $output, $returnVar); exec($this->command($document), $output, $returnVar);
@ -41,15 +48,41 @@ abstract class BaseCompiler implements Responsable
return $this; return $this;
} }
/**
* @param array<int, Documents> $documents
*/
public function merge(array $documents): self
{
$outfile = '/tmp/' . Str::uuid()->toString() . '.pdf';
$paths = array_map(fn ($document) => static::compile($document)->getPath(), $documents);
$command = collect([
'pdfjam --nup 1x1 --outfile ' . $outfile,
...array_map(fn ($path) => escapeshellarg($path), $paths),
])->implode(' ');
exec($command, $output, $returnVar);
foreach ($paths as $path) {
@unlink($path);
}
if (0 !== $returnVar) {
Log::error('Merging failed', ['output' => $output]);
throw (new CompilerException('Compilation failed.'))->setOutput($output);
}
return static::fromFile($outfile);
}
public function storeAs(string $directory, string $name, string $disk): string public function storeAs(string $directory, string $name, string $disk): string
{ {
$contents = $this->file->getContent(); $contents = $this->file->getContent();
Storage::disk($disk)->put($directory.'/'.$name, $contents); Storage::disk($disk)->put($directory . '/' . $name, $contents);
$this->cleanup(); $this->cleanup();
return $directory.'/'.$name; return $directory . '/' . $name;
} }
public function storeIn(string $directory, string $disk): string public function storeIn(string $directory, string $disk): string
@ -72,9 +105,9 @@ abstract class BaseCompiler implements Responsable
protected function prepareForCompilation(Document $document): void protected function prepareForCompilation(Document $document): void
{ {
$workDir = '/tmp/'.Str::random(32); $workDir = '/tmp/' . Str::uuid()->toString();
mkdir($workDir, 0777, true); mkdir($workDir, 0777, true);
$this->file = new File($workDir.'/'.$document->compiledFilename(), false); $this->file = new File($workDir . '/' . $document->compiledFilename(), false);
} }
private function refreshFile(): void private function refreshFile(): void
@ -85,14 +118,14 @@ abstract class BaseCompiler implements Responsable
private function command(Document $document): string private function command(Document $document): string
{ {
return collect([ return collect([
'cd '.escapeshellarg($this->file->getPath()), 'cd ' . escapeshellarg($this->file->getPath()),
$document->getEngine()->binary().' --halt-on-error '.escapeshellarg($document->filename()), $document->getEngine()->binary() . ' --halt-on-error ' . escapeshellarg($document->filename()),
$document->getEngine()->binary().' --halt-on-error '.escapeshellarg($document->filename()), $document->getEngine()->binary() . ' --halt-on-error ' . escapeshellarg($document->filename()),
])->implode(' && '); ])->implode(' && ');
} }
private function cleanup(): void private function cleanup(): void
{ {
exec('rm -R '.$this->file->getPath()); exec('rm -R ' . $this->file->getPath());
} }
} }

View File

@ -8,8 +8,9 @@ use PHPUnit\Framework\Assert;
use ReflectionClass; use ReflectionClass;
use ReflectionMethod; use ReflectionMethod;
use ReflectionProperty; use ReflectionProperty;
use Spatie\LaravelData\Data;
abstract class Document abstract class Document extends Data
{ {
abstract public function basename(): string; abstract public function basename(): string;
@ -35,6 +36,15 @@ abstract class Document
); );
} }
public function assertIsContent(string $content): void
{
Assert::assertEquals(
$content,
$this->renderBody(),
"Failed asserting that Content is {$content}"
);
}
/** /**
* @param array<int, string> $content * @param array<int, string> $content
*/ */
@ -80,12 +90,12 @@ abstract class Document
public function filename(): string public function filename(): string
{ {
return $this->basename().'.tex'; return $this->basename() . '.tex';
} }
public function compiledFilename(): string public function compiledFilename(): string
{ {
return $this->basename().'.pdf'; return $this->basename() . '.pdf';
} }
/** /**
@ -144,8 +154,8 @@ abstract class Document
protected function createVariableFromMethod(ReflectionMethod $method): Closure|InvokableComponentVariable protected function createVariableFromMethod(ReflectionMethod $method): Closure|InvokableComponentVariable
{ {
return 0 === $method->getNumberOfParameters() return 0 === $method->getNumberOfParameters()
? $this->createInvokableVariable($method->getName()) ? $this->createInvokableVariable($method->getName())
: Closure::fromCallable([$this, $method->getName()]); : Closure::fromCallable([$this, $method->getName()]);
} }
protected function createInvokableVariable(string $method): InvokableComponentVariable protected function createInvokableVariable(string $method): InvokableComponentVariable

View File

@ -22,12 +22,21 @@ trait FakesCompilation
Assert::assertFalse( Assert::assertFalse(
$compilations->isEmpty(), $compilations->isEmpty(),
'The TeX Document "'.$documentClass.'" has not been compiled.' 'The TeX Document "' . $documentClass . '" has not been compiled.'
); );
$validDocuments = $compilations->filter(fn ($compilation) => $check($compilation)); $validDocuments = $compilations->filter(fn ($compilation) => $check($compilation));
Assert::assertNotEmpty($validDocuments, 'Failed that TeX Document "'.$documentClass.'" has been compiled with given check.'); Assert::assertNotEmpty($validDocuments, 'Failed that TeX Document "' . $documentClass . '" has been compiled with given check.');
}
/**
* @param class-string<Document> $documentClass
* @param callable(Document): bool $check
*/
public function assertCompiledContent(string $documentClass, string $content): void
{
$this->assertCompiled($documentClass, fn ($document) => $document->renderBody() === $content);
} }
/** /**
@ -39,7 +48,7 @@ trait FakesCompilation
Assert::assertTrue( Assert::assertTrue(
$compilations->isEmpty(), $compilations->isEmpty(),
'The TeX Document "'.$documentClass.'" should not have been compiled.' 'The TeX Document "' . $documentClass . '" should not have been compiled.'
); );
} }