tex/src/Document.php

168 lines
4.1 KiB
PHP

<?php
namespace Zoomyboy\Tex;
use Closure;
use Illuminate\View\InvokableComponentVariable;
use PHPUnit\Framework\Assert;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use Spatie\LaravelData\Data;
abstract class Document extends Data
{
abstract public function basename(): string;
abstract public function view(): string;
abstract public function template(): ?Template;
abstract public function getEngine(): Engine;
public function renderBody(): string
{
return view()
->make($this->view(), $this->data())
->render();
}
public function assertHasContent(string $content): void
{
Assert::assertStringContainsString(
$content,
$this->renderBody(),
"Failed asserting that Content contains {$content}"
);
}
public function assertIsContent(string $content): void
{
Assert::assertEquals(
$content,
$this->renderBody(),
"Failed asserting that Content is {$content}"
);
}
/**
* @param array<int, string> $content
*/
public function assertHasAllContent(array $content): void
{
foreach ($content as $test) {
$this->assertHasContent($test);
}
}
public function hasContent(string $content): bool
{
return str_contains($this->renderBody(), $content);
}
/**
* @param array<int, string> $content
*/
public function hasAllContent(array $content): bool
{
foreach ($content as $check) {
if (!$this->hasContent($check)) {
return false;
}
}
return true;
}
/**
* @param array<int, string> $content
*/
public function missesAllContent(array $content): bool
{
foreach ($content as $check) {
if ($this->hasContent($check)) {
return false;
}
}
return true;
}
public function filename(): string
{
return $this->basename() . '.tex';
}
public function compiledFilename(): string
{
return $this->basename() . '.pdf';
}
/**
* @return array<string, mixed>
*/
public function data(): array
{
return array_merge($this->extractPublicProperties(), $this->extractPublicMethods());
}
/**
* @return array<string, mixed>
*/
protected function extractPublicProperties(): array
{
$class = get_class($this);
$reflection = new ReflectionClass($this);
$properties = collect($reflection->getProperties(ReflectionProperty::IS_PUBLIC))
->filter(fn (ReflectionProperty $property) => !$property->isStatic());
$values = [];
foreach ($properties as $property) {
$values[$property->getName()] = $this->{$property->getName()};
}
return $values;
}
/**
* Extract the public methods for the component.
*
* @return array<string, Closure|InvokableComponentVariable>
*/
protected function extractPublicMethods()
{
$class = get_class($this);
$reflection = new ReflectionClass($this);
/* @var Collection<string, string> */
$methods = collect($reflection->getMethods(ReflectionMethod::IS_PUBLIC))
->all();
$values = [];
foreach ($methods as $method) {
$values[$method->getName()] = $this->createVariableFromMethod(new ReflectionMethod($this, $method->getName()));
}
return $values;
}
protected function createVariableFromMethod(ReflectionMethod $method): Closure|InvokableComponentVariable
{
return 0 === $method->getNumberOfParameters()
? $this->createInvokableVariable($method->getName())
: Closure::fromCallable([$this, $method->getName()]);
}
protected function createInvokableVariable(string $method): InvokableComponentVariable
{
return new InvokableComponentVariable(function () use ($method) {
return $this->{$method}();
});
}
}