180 lines
5.3 KiB
PHP
180 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace App;
|
|
|
|
use App\Http\Router;
|
|
use App\Http\ServerRequest;
|
|
use DI\FactoryInterface;
|
|
use Doctrine\Inflector\InflectorFactory;
|
|
use League\Plates\Engine;
|
|
use League\Plates\Template\Data;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
|
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
|
|
|
class View extends Engine
|
|
{
|
|
protected Assets $assets;
|
|
|
|
protected ?ServerRequestInterface $request = null;
|
|
|
|
public function __construct(
|
|
FactoryInterface $factory,
|
|
Environment $environment,
|
|
EventDispatcher $dispatcher,
|
|
Version $version,
|
|
?ServerRequestInterface $request = null
|
|
) {
|
|
parent::__construct($environment->getViewsDirectory(), 'phtml');
|
|
|
|
// Add non-request-dependent content.
|
|
$this->assets = $factory->make(
|
|
Assets::class,
|
|
[
|
|
'request' => $request,
|
|
]
|
|
);
|
|
|
|
$this->addData(
|
|
[
|
|
'environment' => $environment,
|
|
'version' => $version,
|
|
'assets' => $this->assets,
|
|
]
|
|
);
|
|
|
|
// Add request-dependent content.
|
|
$this->request = $request;
|
|
|
|
if ($request instanceof ServerRequestInterface) {
|
|
$this->addData(
|
|
[
|
|
'request' => $request,
|
|
'router' => $request->getAttribute(ServerRequest::ATTR_ROUTER),
|
|
'auth' => $request->getAttribute(ServerRequest::ATTR_AUTH),
|
|
'acl' => $request->getAttribute(ServerRequest::ATTR_ACL),
|
|
'customization' => $request->getAttribute(ServerRequest::ATTR_CUSTOMIZATION),
|
|
'flash' => $request->getAttribute(ServerRequest::ATTR_SESSION_FLASH),
|
|
'user' => $request->getAttribute(ServerRequest::ATTR_USER),
|
|
]
|
|
);
|
|
} else {
|
|
$this->addData(
|
|
[
|
|
'router' => $factory->make(Router::class),
|
|
]
|
|
);
|
|
}
|
|
|
|
$this->registerFunction(
|
|
'escapeJs',
|
|
function ($string) {
|
|
return json_encode($string, JSON_THROW_ON_ERROR, 512);
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'dump',
|
|
function ($value) {
|
|
if (class_exists(VarCloner::class)) {
|
|
$varCloner = new VarCloner();
|
|
|
|
$dumper = new CliDumper();
|
|
$dumpedValue = $dumper->dump($varCloner->cloneVar($value), true);
|
|
} else {
|
|
$dumpedValue = json_encode($value, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
return '<pre>' . htmlspecialchars($dumpedValue) . '</pre>';
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'mailto',
|
|
function ($address, $link_text = null) {
|
|
$address = substr(chunk_split(bin2hex(" $address"), 2, ';&#x'), 3, -3);
|
|
$link_text = $link_text ?? $address;
|
|
return '<a href="mailto:' . $address . '">' . $link_text . '</a>';
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'pluralize',
|
|
function ($word, $num = 0) {
|
|
if ((int)$num === 1) {
|
|
return $word;
|
|
}
|
|
|
|
$inflector = InflectorFactory::create()->build();
|
|
return $inflector->pluralize($word);
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'truncate',
|
|
function ($text, $length = 80) {
|
|
return Utilities\Strings::truncateText($text, $length);
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'truncateUrl',
|
|
function ($url) {
|
|
return Utilities\Strings::truncateUrl($url);
|
|
}
|
|
);
|
|
|
|
$this->registerFunction(
|
|
'link',
|
|
function ($url, $external = true, $truncate = true) {
|
|
$url = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
|
|
|
|
$a = ['href="' . $url . '"'];
|
|
if ($external) {
|
|
$a[] = 'target="_blank"';
|
|
}
|
|
|
|
$a_body = ($truncate) ? Utilities\Strings::truncateUrl($url) : $url;
|
|
return '<a ' . implode(' ', $a) . '>' . $a_body . '</a>';
|
|
}
|
|
);
|
|
|
|
$dispatcher->dispatch(new Event\BuildView($this));
|
|
}
|
|
|
|
public function reset(): void
|
|
{
|
|
$this->data = new Data();
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param array $data
|
|
*/
|
|
public function fetch(string $name, array $data = []): string
|
|
{
|
|
return $this->render($name, $data);
|
|
}
|
|
|
|
/**
|
|
* Trigger rendering of template and write it directly to the PSR-7 compatible Response object.
|
|
*
|
|
* @param ResponseInterface $response
|
|
* @param string $templateName
|
|
* @param array $templateArgs
|
|
*/
|
|
public function renderToResponse(
|
|
ResponseInterface $response,
|
|
string $templateName,
|
|
array $templateArgs = []
|
|
): ResponseInterface {
|
|
$template = $this->render($templateName, $templateArgs);
|
|
|
|
$response->getBody()->write($template);
|
|
$response = $response->withHeader('Content-type', 'text/html; charset=utf-8');
|
|
|
|
return $this->assets->writeCsp($response);
|
|
}
|
|
}
|