Merge remote-tracking branch 'MyIgel/templating'
commit
222c9fed7d
@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Return currently active locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function locale()
|
||||
{
|
||||
return session()->get('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns two letter language code from currently active locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function locale_short()
|
||||
{
|
||||
return substr(locale(), 0, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes gettext for internationalization and updates the sessions locale to use for translation.
|
||||
*/
|
||||
function gettext_init()
|
||||
{
|
||||
$locales = config('locales');
|
||||
$request = request();
|
||||
$session = session();
|
||||
|
||||
if ($request->has('set_locale') && isset($locales[$request->input('set_locale')])) {
|
||||
$session->set('locale', $request->input('set_locale'));
|
||||
} elseif (!$session->has('locale')) {
|
||||
$session->set('locale', config('default_locale'));
|
||||
}
|
||||
|
||||
gettext_locale();
|
||||
bindtextdomain('default', app('path.lang'));
|
||||
bind_textdomain_codeset('default', 'UTF-8');
|
||||
textdomain('default');
|
||||
}
|
||||
|
||||
/**
|
||||
* Swich gettext locale.
|
||||
*
|
||||
* @param string $locale
|
||||
*/
|
||||
function gettext_locale($locale = null)
|
||||
{
|
||||
if (empty($locale)) {
|
||||
$locale = session()->get('locale');
|
||||
}
|
||||
|
||||
putenv('LC_ALL=' . $locale);
|
||||
setlocale(LC_ALL, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders language selection.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function make_langselect()
|
||||
{
|
||||
$request = app('request');
|
||||
|
||||
$items = [];
|
||||
foreach (config('locales') as $locale => $name) {
|
||||
$url = url($request->getPathInfo(), ['set_locale' => $locale]);
|
||||
|
||||
$items[] = toolbar_item_link(
|
||||
htmlspecialchars($url),
|
||||
'',
|
||||
$name,
|
||||
$locale == locale()
|
||||
);
|
||||
}
|
||||
return $items;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Helpers;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
class TranslationServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
/** @var Config $config */
|
||||
$config = $this->app->get('config');
|
||||
/** @var Session $session */
|
||||
$session = $this->app->get('session');
|
||||
|
||||
$locales = $config->get('locales');
|
||||
$locale = $config->get('default_locale');
|
||||
|
||||
$sessionLocale = $session->get('locale', $locale);
|
||||
if (isset($locales[$sessionLocale])) {
|
||||
$locale = $sessionLocale;
|
||||
}
|
||||
|
||||
$this->initGettext();
|
||||
$session->set('locale', $locale);
|
||||
|
||||
$translator = $this->app->make(
|
||||
Translator::class,
|
||||
['locale' => $locale, 'locales' => $locales, 'localeChangeCallback' => [$this, 'setLocale']]
|
||||
);
|
||||
$this->app->instance(Translator::class, $translator);
|
||||
$this->app->instance('translator', $translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $textDomain
|
||||
* @param string $encoding
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function initGettext($textDomain = 'default', $encoding = 'UTF-8')
|
||||
{
|
||||
bindtextdomain($textDomain, $this->app->get('path.lang'));
|
||||
bind_textdomain_codeset($textDomain, $encoding);
|
||||
textdomain($textDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setLocale($locale)
|
||||
{
|
||||
putenv('LC_ALL=' . $locale);
|
||||
setlocale(LC_ALL, $locale);
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Helpers;
|
||||
|
||||
class Translator
|
||||
{
|
||||
/** @var string[] */
|
||||
protected $locales;
|
||||
|
||||
/** @var string */
|
||||
protected $locale;
|
||||
|
||||
/** @var callable */
|
||||
protected $localeChangeCallback;
|
||||
|
||||
/**
|
||||
* Translator constructor.
|
||||
*
|
||||
* @param string $locale
|
||||
* @param string[] $locales
|
||||
* @param callable $localeChangeCallback
|
||||
*/
|
||||
public function __construct(string $locale, array $locales = [], callable $localeChangeCallback = null)
|
||||
{
|
||||
$this->localeChangeCallback = $localeChangeCallback;
|
||||
|
||||
$this->setLocale($locale);
|
||||
$this->setLocales($locales);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the translation for a given key
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $replace
|
||||
* @return string
|
||||
*/
|
||||
public function translate(string $key, array $replace = []): string
|
||||
{
|
||||
$translated = $this->translateGettext($key);
|
||||
|
||||
if (!empty($replace)) {
|
||||
$translated = call_user_func_array('sprintf', array_merge([$translated], $replace));
|
||||
}
|
||||
|
||||
return $translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the key via gettext
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function translateGettext(string $key): string
|
||||
{
|
||||
return _($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale(): string
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setLocale(string $locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
|
||||
if (is_callable($this->localeChangeCallback)) {
|
||||
call_user_func_array($this->localeChangeCallback, [$locale]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getLocales(): array
|
||||
{
|
||||
return $this->locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @return bool
|
||||
*/
|
||||
public function hasLocale(string $locale): bool
|
||||
{
|
||||
return isset($this->locales[$locale]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $locales
|
||||
*/
|
||||
public function setLocales(array $locales)
|
||||
{
|
||||
$this->locales = $locales;
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Http\Response;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Twig_LoaderInterface as TwigLoader;
|
||||
|
||||
class ErrorHandler implements MiddlewareInterface
|
||||
{
|
||||
/** @var TwigLoader */
|
||||
protected $loader;
|
||||
|
||||
/** @var string */
|
||||
protected $viewPrefix = 'errors/';
|
||||
|
||||
/**
|
||||
* @param TwigLoader $loader
|
||||
*/
|
||||
public function __construct(TwigLoader $loader)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles any error messages
|
||||
*
|
||||
* Should be added at the beginning
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(
|
||||
ServerRequestInterface $request,
|
||||
RequestHandlerInterface $handler
|
||||
): ResponseInterface {
|
||||
$response = $handler->handle($request);
|
||||
|
||||
$statusCode = $response->getStatusCode();
|
||||
if ($statusCode < 400 || !$response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$view = $this->selectView($statusCode);
|
||||
|
||||
return $response->withView(
|
||||
$this->viewPrefix . $view,
|
||||
[
|
||||
'status' => $statusCode,
|
||||
'content' => $response->getContent(),
|
||||
],
|
||||
$statusCode,
|
||||
$response->getHeaders()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a view based on the given status code
|
||||
*
|
||||
* @param int $statusCode
|
||||
* @return string
|
||||
*/
|
||||
protected function selectView(int $statusCode): string
|
||||
{
|
||||
$hundreds = intdiv($statusCode, 100);
|
||||
|
||||
$viewsList = [$statusCode, $hundreds, $hundreds * 100];
|
||||
foreach ($viewsList as $view) {
|
||||
if ($this->loader->exists($this->viewPrefix . $view)) {
|
||||
return $view;
|
||||
}
|
||||
}
|
||||
|
||||
return 'default';
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Middleware;
|
||||
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
class SetLocale implements MiddlewareInterface
|
||||
{
|
||||
/** @var Translator */
|
||||
protected $translator;
|
||||
|
||||
/** @var Session */
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* @param Translator $translator
|
||||
* @param Session $session
|
||||
*/
|
||||
public function __construct(Translator $translator, Session $session)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and setting the locale if required
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$query = $request->getQueryParams();
|
||||
if (isset($query['set-locale']) && $this->translator->hasLocale($query['set-locale'])) {
|
||||
$locale = $query['set-locale'];
|
||||
|
||||
$this->translator->setLocale($locale);
|
||||
$this->session->set('locale', $locale);
|
||||
}
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Config\Config as EngelsystemConfig;
|
||||
use Twig_Extension as TwigExtension;
|
||||
use Twig_Function as TwigFunction;
|
||||
|
||||
class Config extends TwigExtension
|
||||
{
|
||||
/** @var EngelsystemConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param EngelsystemConfig $config
|
||||
*/
|
||||
public function __construct(EngelsystemConfig $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('config', [$this->config, 'get']),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer\Twig\Extensions;
|
||||
|
||||
use Twig_Extension as TwigExtension;
|
||||
use Twig_Extension_GlobalsInterface as GlobalsInterface;
|
||||
|
||||
class Globals extends TwigExtension implements GlobalsInterface
|
||||
{
|
||||
/**
|
||||
* Returns a list of global variables to add to the existing list.
|
||||
*
|
||||
* @return array An array of global variables
|
||||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
global $user;
|
||||
|
||||
return [
|
||||
'user' => isset($user) ? $user : [],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer\Twig\Extensions;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Session as SymfonySession;
|
||||
use Twig_Extension as TwigExtension;
|
||||
use Twig_Function as TwigFunction;
|
||||
|
||||
class Session extends TwigExtension
|
||||
{
|
||||
/** @var SymfonySession */
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* @param SymfonySession $session
|
||||
*/
|
||||
public function __construct(SymfonySession $session)
|
||||
{
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('session_get', [$this->session, 'get']),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Twig_Extension as TwigExtension;
|
||||
use Twig_Extensions_TokenParser_Trans as TranslationTokenParser;
|
||||
use Twig_Filter as TwigFilter;
|
||||
use Twig_Function as TwigFunction;
|
||||
use Twig_TokenParserInterface as TwigTokenParser;
|
||||
|
||||
class Translation extends TwigExtension
|
||||
{
|
||||
/** @var Translator */
|
||||
protected $translator;
|
||||
|
||||
/** @var TranslationTokenParser */
|
||||
protected $tokenParser;
|
||||
|
||||
/**
|
||||
* @param Translator $translator
|
||||
* @param TranslationTokenParser $tokenParser
|
||||
*/
|
||||
public function __construct(Translator $translator, TranslationTokenParser $tokenParser)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->tokenParser = $tokenParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return [
|
||||
new TwigFilter('trans', [$this->translator, 'translate']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('__', [$this->translator, 'translate']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigTokenParser[]
|
||||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return [$this->tokenParser];
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Http\UrlGenerator;
|
||||
use Twig_Extension as TwigExtension;
|
||||
use Twig_Function as TwigFunction;
|
||||
|
||||
class Url extends TwigExtension
|
||||
{
|
||||
/** @var UrlGenerator */
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* @param UrlGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct(UrlGenerator $urlGenerator)
|
||||
{
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigFunction[]
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('url', [$this, 'getUrl']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $parameters
|
||||
* @return UrlGenerator|string
|
||||
*/
|
||||
public function getUrl($path, $parameters = [])
|
||||
{
|
||||
$path = str_replace('_', '-', $path);
|
||||
|
||||
return $this->urlGenerator->to($path, $parameters);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer;
|
||||
|
||||
use Twig_Environment as Twig;
|
||||
use Twig_Error_Loader as LoaderError;
|
||||
use Twig_Error_Runtime as RuntimeError;
|
||||
use Twig_Error_Syntax as SyntaxError;
|
||||
|
||||
class TwigEngine implements EngineInterface
|
||||
{
|
||||
/** @var Twig */
|
||||
protected $twig;
|
||||
|
||||
public function __construct(Twig $twig)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a twig template
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $data
|
||||
* @return string
|
||||
* @throws LoaderError|RuntimeError|SyntaxError
|
||||
*/
|
||||
public function get($path, $data = [])
|
||||
{
|
||||
return $this->twig->render($path, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public function canRender($path)
|
||||
{
|
||||
return $this->twig->getLoader()->exists($path);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer;
|
||||
|
||||
use Twig_Error_Loader;
|
||||
use Twig_Loader_Filesystem as FilesystemLoader;
|
||||
|
||||
class TwigLoader extends FilesystemLoader
|
||||
{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param bool $throw
|
||||
* @return false|string
|
||||
* @throws Twig_Error_Loader
|
||||
*/
|
||||
public function findTemplate($name, $throw = true)
|
||||
{
|
||||
$extension = '.twig';
|
||||
$extensionLength = strlen($extension);
|
||||
if (substr($name, -$extensionLength, $extensionLength) !== $extension) {
|
||||
$name .= $extension;
|
||||
}
|
||||
|
||||
return parent::findTemplate($name, $throw);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Config;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Globals;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Session;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Translation;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Url;
|
||||
use Twig_Environment as Twig;
|
||||
use Twig_LoaderInterface as TwigLoaderInterface;
|
||||
|
||||
class TwigServiceProvider extends ServiceProvider
|
||||
{
|
||||
/** @var array */
|
||||
protected $extensions = [
|
||||
'config' => Config::class,
|
||||
'globals' => Globals::class,
|
||||
'session' => Session::class,
|
||||
'url' => Url::class,
|
||||
'translation' => Translation::class,
|
||||
];
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->registerTwigEngine();
|
||||
|
||||
foreach ($this->extensions as $alias => $class) {
|
||||
$this->registerTwigExtensions($class, $alias);
|
||||
}
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
/** @var Twig $renderer */
|
||||
$renderer = $this->app->get('twig.environment');
|
||||
|
||||
foreach ($this->app->tagged('twig.extension') as $extension) {
|
||||
$renderer->addExtension($extension);
|
||||
}
|
||||
}
|
||||
|
||||
protected function registerTwigEngine()
|
||||
{
|
||||
$viewsPath = $this->app->get('path.views');
|
||||
|
||||
$twigLoader = $this->app->make(TwigLoader::class, ['paths' => $viewsPath]);
|
||||
$this->app->instance(TwigLoader::class, $twigLoader);
|
||||
$this->app->instance(TwigLoaderInterface::class, $twigLoader);
|
||||
$this->app->instance('twig.loader', $twigLoader);
|
||||
|
||||
$twig = $this->app->make(Twig::class);
|
||||
$this->app->instance(Twig::class, $twig);
|
||||
$this->app->instance('twig.environment', $twig);
|
||||
|
||||
$twigEngine = $this->app->make(TwigEngine::class);
|
||||
$this->app->instance('renderer.twigEngine', $twigEngine);
|
||||
$this->app->tag('renderer.twigEngine', ['renderer.engine']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $alias
|
||||
*/
|
||||
protected function registerTwigExtensions($class, $alias)
|
||||
{
|
||||
$alias = 'twig.extension.' . $alias;
|
||||
|
||||
$extension = $this->app->make($class);
|
||||
|
||||
$this->app->instance($class, $extension);
|
||||
$this->app->instance($alias, $extension);
|
||||
|
||||
$this->app->tag($alias, ['twig.extension']);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{% extends "layouts/app.twig" %}
|
||||
|
||||
{% block title %}{% if status == 404 %}{{ __("Page not found") }}{% else %}Error {{ status }}{% endif %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="alert alert-info">{{ content }}</div>
|
||||
{% endblock %}
|
@ -1,46 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="%locale%">
|
||||
<head>
|
||||
<title>%title% - Engelsystem</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="%start_page_url%assets/theme%theme%.css"/>
|
||||
<script type="text/javascript" src="%start_page_url%assets/vendor.js"></script>
|
||||
%atom_link%
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed"
|
||||
data-toggle="collapse" data-target="#navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="%start_page_url%">
|
||||
<span class="icon-icon_angel"></span> <strong class="visible-lg-inline">ENGELSYSTEM</strong>
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse-1">%menu% %header_toolbar%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">%content%</div>
|
||||
<div class="row" id="footer">
|
||||
<div class="col-md-12">
|
||||
<hr/>
|
||||
<div class="text-center footer" style="margin-bottom: 10px;">
|
||||
%event_info%
|
||||
<a href="%faq_url%">FAQ</a>
|
||||
· <a href="%contact_email%"><span class="glyphicon glyphicon-envelope"></span> Contact</a>
|
||||
· <a href="https://github.com/engelsystem/engelsystem/issues">Bugs / Features</a>
|
||||
· <a href="https://github.com/engelsystem/engelsystem/">Development Platform</a>
|
||||
· <a href="%credits_url%">Credits</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,87 @@
|
||||
{% set theme = user.color|default(config('theme')) %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{% block head %}
|
||||
<title>{% block title %}{{ title }}{% endblock %} - Engelsystem</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="css/theme{{ theme }}.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="vendor/icomoon/style.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="vendor/bootstrap-datepicker-1.7.1/css/bootstrap-datepicker3.min.css"/>
|
||||
<script type="text/javascript" src="vendor/jquery-2.1.1.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/jquery-ui.min.js"></script>
|
||||
{% if atom_feed -%}
|
||||
<link href="{{ url('atom', atom_feed) }}" type="application/atom+xml" rel="alternate" title="Atom Feed">
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% block body %}
|
||||
<div class="navbar navbar-default navbar-fixed-top">
|
||||
{% block header %}
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed"
|
||||
data-toggle="collapse" data-target="#navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
<span class="icon-icon_angel"></span> <strong class="visible-lg-inline">ENGELSYSTEM</strong>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% block navbar %}
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse-1">
|
||||
{{ menu|raw }}
|
||||
{{ header_toolbar|raw }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">{% block content %}{{ content|raw }}{% endblock %}</div>
|
||||
<div class="row" id="footer">
|
||||
{% block footer %}
|
||||
<div class="col-md-12">
|
||||
<hr/>
|
||||
<div class="text-center footer" style="margin-bottom: 10px;">
|
||||
{% block eventinfo %}
|
||||
{{ event_info|raw }}
|
||||
{% endblock %}
|
||||
<a href="{{ config('faq_url') }}">FAQ</a>
|
||||
· <a href="{{ config('contact_email') }}">
|
||||
<span class="glyphicon glyphicon-envelope"></span>Contact
|
||||
</a>
|
||||
· <a href="https://github.com/engelsystem/engelsystem/issues">Bugs / Features</a>
|
||||
· <a href="https://github.com/engelsystem/engelsystem/">Development Platform</a>
|
||||
· <a href="{{ url('credits') }}">Credits</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/js/bootstrap-datepicker.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/bootstrap-datepicker-1.7.1/locales/bootstrap-datepicker.de.min.js"></script>
|
||||
<script type="text/javascript" src="vendor/Chart.min.js"></script>
|
||||
<script type="text/javascript" src="js/forms.js"></script>
|
||||
<script type="text/javascript" src="vendor/moment-with-locales.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
moment.locale("{{ session_get('locale')|escape('js') }}");
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript" src="js/moment-countdown.js"></script>
|
||||
<script type="text/javascript" src="js/sticky-headers.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Helpers;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Helpers\TranslationServiceProvider;
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
class TranslationServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\TranslationServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
$app = $this->getApp(['make', 'instance', 'get']);
|
||||
/** @var Config|MockObject $config */
|
||||
$config = $this->createMock(Config::class);
|
||||
/** @var Session|MockObject $session */
|
||||
$session = $this->createMock(Session::class);
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->createMock(Translator::class);
|
||||
|
||||
/** @var TranslationServiceProvider|MockObject $serviceProvider */
|
||||
$serviceProvider = $this->getMockBuilder(TranslationServiceProvider::class)
|
||||
->setConstructorArgs([$app])
|
||||
->setMethods(['initGettext', 'setLocale'])
|
||||
->getMock();
|
||||
|
||||
$serviceProvider->expects($this->once())
|
||||
->method('initGettext');
|
||||
|
||||
$app->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->withConsecutive(['config'], ['session'])
|
||||
->willReturnOnConsecutiveCalls($config, $session);
|
||||
|
||||
$defaultLocale = 'fo_OO';
|
||||
$locale = 'te_ST.WTF-9';
|
||||
$locales = ['fo_OO' => 'Foo', 'fo_OO.BAR' => 'Foo (Bar)', 'te_ST.WTF-9' => 'WTF\'s Testing?'];
|
||||
$config->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->withConsecutive(
|
||||
['locales'],
|
||||
['default_locale']
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
$locales,
|
||||
$defaultLocale
|
||||
);
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('get')
|
||||
->with('locale', $defaultLocale)
|
||||
->willReturn($locale);
|
||||
$session->expects($this->once())
|
||||
->method('set')
|
||||
->with('locale', $locale);
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('make')
|
||||
->with(
|
||||
Translator::class,
|
||||
[
|
||||
'locale' => $locale,
|
||||
'locales' => $locales,
|
||||
'localeChangeCallback' => [$serviceProvider, 'setLocale']
|
||||
]
|
||||
)
|
||||
->willReturn($translator);
|
||||
|
||||
$app->expects($this->exactly(2))
|
||||
->method('instance')
|
||||
->withConsecutive(
|
||||
[Translator::class, $translator],
|
||||
['translator', $translator]
|
||||
);
|
||||
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Helpers;
|
||||
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use stdClass;
|
||||
|
||||
class TranslatorTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translator::__construct()
|
||||
* @covers \Engelsystem\Helpers\Translator::setLocale()
|
||||
* @covers \Engelsystem\Helpers\Translator::setLocales()
|
||||
* @covers \Engelsystem\Helpers\Translator::getLocale()
|
||||
* @covers \Engelsystem\Helpers\Translator::getLocales()
|
||||
* @covers \Engelsystem\Helpers\Translator::hasLocale()
|
||||
*/
|
||||
public function testInit()
|
||||
{
|
||||
$locales = ['te_ST.ER-01' => 'Tests', 'fo_OO' => 'SomeFOO'];
|
||||
$locale = 'te_ST.ER-01';
|
||||
|
||||
/** @var callable|MockObject $callable */
|
||||
$callable = $this->getMockBuilder(stdClass::class)
|
||||
->setMethods(['__invoke'])
|
||||
->getMock();
|
||||
$callable->expects($this->exactly(2))
|
||||
->method('__invoke')
|
||||
->withConsecutive(['te_ST.ER-01'], ['fo_OO']);
|
||||
|
||||
$translator = new Translator($locale, $locales, $callable);
|
||||
|
||||
$this->assertEquals($locales, $translator->getLocales());
|
||||
$this->assertEquals($locale, $translator->getLocale());
|
||||
|
||||
$translator->setLocale('fo_OO');
|
||||
$this->assertEquals('fo_OO', $translator->getLocale());
|
||||
|
||||
$newLocales = ['lo_RM' => 'Lorem', 'ip_SU-M' => 'Ipsum'];
|
||||
$translator->setLocales($newLocales);
|
||||
$this->assertEquals($newLocales, $translator->getLocales());
|
||||
|
||||
$this->assertTrue($translator->hasLocale('ip_SU-M'));
|
||||
$this->assertFalse($translator->hasLocale('te_ST.ER-01'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translator::translate()
|
||||
*/
|
||||
public function testTranslate()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->getMockBuilder(Translator::class)
|
||||
->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
|
||||
->setMethods(['translateGettext'])
|
||||
->getMock();
|
||||
$translator->expects($this->once())
|
||||
->method('translateGettext')
|
||||
->with('My favourite number is %u!')
|
||||
->willReturn('Meine Lieblingszahl ist die %u!');
|
||||
|
||||
$return = $translator->translate('My favourite number is %u!', [3]);
|
||||
$this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Middleware\ErrorHandler;
|
||||
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddlewareHandler;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Twig_LoaderInterface as TwigLoader;
|
||||
|
||||
class ErrorHandlerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\ErrorHandler::__construct
|
||||
* @covers \Engelsystem\Middleware\ErrorHandler::process
|
||||
* @covers \Engelsystem\Middleware\ErrorHandler::selectView
|
||||
*/
|
||||
public function testProcess()
|
||||
{
|
||||
/** @var TwigLoader|MockObject $twigLoader */
|
||||
$twigLoader = $this->createMock(TwigLoader::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->createMock(ServerRequestInterface::class);
|
||||
/** @var ResponseInterface|MockObject $psrResponse */
|
||||
$psrResponse = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
$returnResponseHandler = new ReturnResponseMiddlewareHandler($psrResponse);
|
||||
|
||||
$psrResponse->expects($this->once())
|
||||
->method('getStatusCode')
|
||||
->willReturn(505);
|
||||
|
||||
$errorHandler = new ErrorHandler($twigLoader);
|
||||
|
||||
$return = $errorHandler->process($request, $returnResponseHandler);
|
||||
$this->assertEquals($psrResponse, $return, 'Plain PSR-7 Response should be passed directly');
|
||||
|
||||
/** @var Response|MockObject $response */
|
||||
$response = $this->createMock(Response::class);
|
||||
|
||||
$response->expects($this->exactly(3))
|
||||
->method('getStatusCode')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
200,
|
||||
418,
|
||||
505
|
||||
);
|
||||
|
||||
$returnResponseHandler->setResponse($response);
|
||||
$return = $errorHandler->process($request, $returnResponseHandler);
|
||||
$this->assertEquals($response, $return, 'Only Responses >= 400 should be processed');
|
||||
|
||||
$twigLoader->expects($this->exactly(4))
|
||||
->method('exists')
|
||||
->withConsecutive(
|
||||
['errors/418'],
|
||||
['errors/4'],
|
||||
['errors/400'],
|
||||
['errors/505']
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
$response->expects($this->exactly(2))
|
||||
->method('getContent')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
'Teapot',
|
||||
'Internal Error!'
|
||||
);
|
||||
|
||||
$response->expects($this->exactly(2))
|
||||
->method('withView')
|
||||
->withConsecutive(
|
||||
['errors/default', ['status' => 418, 'content' => 'Teapot'], 418],
|
||||
['errors/505', ['status' => 505, 'content' => 'Internal Error!'], 505]
|
||||
)
|
||||
->willReturn($response);
|
||||
|
||||
$errorHandler->process($request, $returnResponseHandler);
|
||||
$errorHandler->process($request, $returnResponseHandler);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Middleware;
|
||||
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Engelsystem\Middleware\SetLocale;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
class SetLocaleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Middleware\SetLocale::__construct
|
||||
* @covers \Engelsystem\Middleware\SetLocale::process
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->createMock(Translator::class);
|
||||
/** @var Session|MockObject $session */
|
||||
$session = $this->createMock(Session::class);
|
||||
/** @var ServerRequestInterface|MockObject $request */
|
||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||
/** @var RequestHandlerInterface|MockObject $handler */
|
||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||
/** @var ResponseInterface|MockObject $response */
|
||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||
|
||||
$locale = 'te_ST.UTF8';
|
||||
|
||||
$request->expects($this->exactly(3))
|
||||
->method('getQueryParams')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[],
|
||||
['set-locale' => 'en_US.UTF8'],
|
||||
['set-locale' => $locale]
|
||||
);
|
||||
|
||||
$translator->expects($this->exactly(2))
|
||||
->method('hasLocale')
|
||||
->withConsecutive(
|
||||
['en_US.UTF8'],
|
||||
[$locale]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
false,
|
||||
true
|
||||
);
|
||||
$translator->expects($this->once())
|
||||
->method('setLocale')
|
||||
->with($locale);
|
||||
|
||||
$session->expects($this->once())
|
||||
->method('set')
|
||||
->with('locale', $locale);
|
||||
|
||||
$handler->expects($this->exactly(3))
|
||||
->method('handle')
|
||||
->with($request)
|
||||
->willReturn($response);
|
||||
|
||||
$middleware = new SetLocale($translator, $session);
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
$middleware->process($request, $handler);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Config\Config as EngelsystemConfig;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Config;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class ConfigTest extends ExtensionTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Config::__construct
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Config::getFunctions
|
||||
*/
|
||||
public function testGetFunctions()
|
||||
{
|
||||
/** @var EngelsystemConfig|MockObject $config */
|
||||
$config = $this->createMock(EngelsystemConfig::class);
|
||||
|
||||
$extension = new Config($config);
|
||||
$functions = $extension->getFunctions();
|
||||
|
||||
$this->assertExtensionExists('config', [$config, 'get'], $functions);
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig_Function as TwigFunction;
|
||||
|
||||
abstract class ExtensionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Assert that a twig filter was registered
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $callback
|
||||
* @param TwigFunction[] $functions
|
||||
*/
|
||||
protected function assertFilterExists($name, $callback, $functions)
|
||||
{
|
||||
foreach ($functions as $function) {
|
||||
if ($function->getName() != $name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->assertEquals($callback, $function->getCallable());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(sprintf('Filter %s not found', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a twig function was registered
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $callback
|
||||
* @param TwigFunction[] $functions
|
||||
*/
|
||||
protected function assertExtensionExists($name, $callback, $functions)
|
||||
{
|
||||
foreach ($functions as $function) {
|
||||
if ($function->getName() != $name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->assertEquals($callback, $function->getCallable());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(sprintf('Function %s not found', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a global exists
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param mixed[] $globals
|
||||
*/
|
||||
protected function assertGlobalsExists($name, $value, $globals)
|
||||
{
|
||||
if (isset($globals[$name])) {
|
||||
$this->assertArraySubset([$name => $value], $globals);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(sprintf('Global %s not found', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a token parser was set
|
||||
*
|
||||
* @param $tokenParser
|
||||
* @param $tokenParsers
|
||||
*/
|
||||
protected function assertTokenParserExists($tokenParser, $tokenParsers)
|
||||
{
|
||||
$this->assertArraySubset(
|
||||
[$tokenParser],
|
||||
$tokenParsers,
|
||||
sprintf('Token parser %s not found', get_class($tokenParser))
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Renderer\Twig\Extensions\Globals;
|
||||
|
||||
class GlobalsTest extends ExtensionTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::getGlobals
|
||||
*/
|
||||
public function testGetGlobals()
|
||||
{
|
||||
$extension = new Globals();
|
||||
$globals = $extension->getGlobals();
|
||||
|
||||
$this->assertGlobalsExists('user', [], $globals);
|
||||
|
||||
global $user;
|
||||
$user['foo'] = 'bar';
|
||||
|
||||
$globals = $extension->getGlobals();
|
||||
$this->assertGlobalsExists('user', ['foo' => 'bar'], $globals);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Renderer\Twig\Extensions\Session;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\HttpFoundation\Session\Session as SymfonySession;
|
||||
|
||||
class SessionTest extends ExtensionTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Session::__construct
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Session::getFunctions
|
||||
*/
|
||||
public function testGetGlobals()
|
||||
{
|
||||
/** @var SymfonySession|MockObject $session */
|
||||
$session = $this->createMock(SymfonySession::class);
|
||||
|
||||
$extension = new Session($session);
|
||||
$functions = $extension->getFunctions();
|
||||
|
||||
$this->assertExtensionExists('session_get', [$session, 'get'], $functions);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Helpers\Translator;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Translation;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Twig_Extensions_TokenParser_Trans as TranslationTokenParser;
|
||||
|
||||
class TranslationTest extends ExtensionTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::__construct
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getFilters
|
||||
*/
|
||||
public function testGeFilters()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->createMock(Translator::class);
|
||||
/** @var TranslationTokenParser|MockObject $parser */
|
||||
$parser = $this->createMock(TranslationTokenParser::class);
|
||||
|
||||
$extension = new Translation($translator, $parser);
|
||||
$filters = $extension->getFilters();
|
||||
|
||||
$this->assertExtensionExists('trans', [$translator, 'translate'], $filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getFunctions
|
||||
*/
|
||||
public function testGetFunctions()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->createMock(Translator::class);
|
||||
/** @var TranslationTokenParser|MockObject $parser */
|
||||
$parser = $this->createMock(TranslationTokenParser::class);
|
||||
|
||||
$extension = new Translation($translator, $parser);
|
||||
$functions = $extension->getFunctions();
|
||||
|
||||
$this->assertExtensionExists('__', [$translator, 'translate'], $functions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Translation::getTokenParsers
|
||||
*/
|
||||
public function testGetTokenParsers()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->createMock(Translator::class);
|
||||
/** @var TranslationTokenParser|MockObject $parser */
|
||||
$parser = $this->createMock(TranslationTokenParser::class);
|
||||
|
||||
$extension = new Translation($translator, $parser);
|
||||
$tokenParsers = $extension->getTokenParsers();
|
||||
|
||||
$this->assertTokenParserExists($parser, $tokenParsers);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
|
||||
|
||||
use Engelsystem\Http\UrlGenerator;
|
||||
use Engelsystem\Renderer\Twig\Extensions\Url;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class UrlTest extends ExtensionTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Url::__construct
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Url::getFunctions
|
||||
*/
|
||||
public function testGetGlobals()
|
||||
{
|
||||
/** @var UrlGenerator|MockObject $urlGenerator */
|
||||
$urlGenerator = $this->createMock(UrlGenerator::class);
|
||||
|
||||
$extension = new Url($urlGenerator);
|
||||
$functions = $extension->getFunctions();
|
||||
|
||||
$this->assertExtensionExists('url', [$extension, 'getUrl'], $functions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public function getUrls()
|
||||
{
|
||||
return [
|
||||
['/', '/', 'http://foo.bar/'],
|
||||
['/foo', '/foo', 'http://foo.bar/foo'],
|
||||
['foo_bar', 'foo-bar', 'http://foo.bar/foo-bar'],
|
||||
['dolor', 'dolor', 'http://foo.bar/dolor?lorem_ipsum=dolor', ['lorem_ipsum' => 'dolor']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getUrls
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $return
|
||||
* @param string $urlTo
|
||||
* @param array $parameters
|
||||
*
|
||||
* @covers \Engelsystem\Renderer\Twig\Extensions\Url::getUrl
|
||||
*/
|
||||
public function testGetUrl($url, $urlTo, $return, $parameters = [])
|
||||
{
|
||||
/** @var UrlGenerator|MockObject $urlGenerator */
|
||||
$urlGenerator = $this->createMock(UrlGenerator::class);
|
||||
|
||||
$urlGenerator->expects($this->once())
|
||||
->method('to')
|
||||
->with($urlTo, $parameters)
|
||||
->willReturn($return);
|
||||
|
||||
$extension = new Url($urlGenerator);
|
||||
$generatedUrl = $extension->getUrl($url, $parameters);
|
||||
|
||||
$this->assertEquals($return, $generatedUrl);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer;
|
||||
|
||||
use Engelsystem\Renderer\TwigEngine;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig_Environment as Twig;
|
||||
use Twig_LoaderInterface as LoaderInterface;
|
||||
|
||||
class TwigEngineTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigEngine::__construct
|
||||
* @covers \Engelsystem\Renderer\TwigEngine::get
|
||||
*/
|
||||
public function testGet()
|
||||
{
|
||||
/** @var Twig|MockObject $twig */
|
||||
$twig = $this->createMock(Twig::class);
|
||||
|
||||
$path = 'foo.twig';
|
||||
$data = ['lorem' => 'ipsum'];
|
||||
|
||||
$twig->expects($this->once())
|
||||
->method('render')
|
||||
->with($path, $data)
|
||||
->willReturn('LoremIpsum!');
|
||||
|
||||
$engine = new TwigEngine($twig);
|
||||
$return = $engine->get($path, $data);
|
||||
$this->assertEquals('LoremIpsum!', $return);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigEngine::canRender
|
||||
*/
|
||||
public function testCanRender()
|
||||
{
|
||||
/** @var Twig|MockObject $twig */
|
||||
$twig = $this->createMock(Twig::class);
|
||||
/** @var LoaderInterface|MockObject $loader */
|
||||
$loader = $this->getMockForAbstractClass(LoaderInterface::class);
|
||||
|
||||
$path = 'foo.twig';
|
||||
|
||||
$twig->expects($this->once())
|
||||
->method('getLoader')
|
||||
->willReturn($loader);
|
||||
$loader->expects($this->once())
|
||||
->method('exists')
|
||||
->with($path)
|
||||
->willReturn(true);
|
||||
|
||||
$engine = new TwigEngine($twig);
|
||||
$return = $engine->canRender($path);
|
||||
$this->assertTrue($return);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer;
|
||||
|
||||
use Engelsystem\Renderer\TwigLoader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionClass as Reflection;
|
||||
|
||||
class TwigLoaderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigLoader::findTemplate
|
||||
*/
|
||||
public function testFindTemplate()
|
||||
{
|
||||
$loader = new TwigLoader();
|
||||
|
||||
$reflection = new Reflection(get_class($loader));
|
||||
$property = $reflection->getProperty('cache');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$realPath = __DIR__ . '/Stub/foo.twig';
|
||||
$property->setValue($loader, ['Stub/foo.twig' => $realPath]);
|
||||
|
||||
$return = $loader->findTemplate('Stub/foo.twig');
|
||||
$this->assertEquals($realPath, $return);
|
||||
|
||||
$return = $loader->findTemplate('Stub/foo');
|
||||
$this->assertEquals($realPath, $return);
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer;
|
||||
|
||||
use Engelsystem\Renderer\TwigEngine;
|
||||
use Engelsystem\Renderer\TwigLoader;
|
||||
use Engelsystem\Renderer\TwigServiceProvider;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use ReflectionClass as Reflection;
|
||||
use stdClass;
|
||||
use Twig_Environment as Twig;
|
||||
use Twig_ExtensionInterface as ExtensionInterface;
|
||||
use Twig_LoaderInterface as TwigLoaderInterface;
|
||||
|
||||
class TwigServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigServiceProvider::register
|
||||
* @covers \Engelsystem\Renderer\TwigServiceProvider::registerTwigExtensions
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
$app = $this->getApp(['make', 'instance', 'tag']);
|
||||
$class = $this->createMock(stdClass::class);
|
||||
|
||||
$className = 'Foo\Bar\Class';
|
||||
$classAlias = 'twig.extension.foo';
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('make')
|
||||
->with('Foo\Bar\Class')
|
||||
->willReturn($class);
|
||||
|
||||
$app->expects($this->exactly(2))
|
||||
->method('instance')
|
||||
->withConsecutive(
|
||||
[$className, $class],
|
||||
[$classAlias, $class]
|
||||
);
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('tag')
|
||||
->with($classAlias, ['twig.extension']);
|
||||
|
||||
/** @var TwigServiceProvider|MockObject $serviceProvider */
|
||||
$serviceProvider = $this->getMockBuilder(TwigServiceProvider::class)
|
||||
->setConstructorArgs([$app])
|
||||
->setMethods(['registerTwigEngine'])
|
||||
->getMock();
|
||||
$serviceProvider->expects($this->once())
|
||||
->method('registerTwigEngine');
|
||||
$this->setExtensionsTo($serviceProvider, ['foo' => 'Foo\Bar\Class']);
|
||||
|
||||
$serviceProvider->register();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigServiceProvider::boot
|
||||
*/
|
||||
public function testBoot()
|
||||
{
|
||||
/** @var Twig|MockObject $twig */
|
||||
$twig = $this->createMock(Twig::class);
|
||||
/** @var ExtensionInterface|MockObject $firsExtension */
|
||||
$firsExtension = $this->getMockForAbstractClass(ExtensionInterface::class);
|
||||
/** @var ExtensionInterface|MockObject $secondExtension */
|
||||
$secondExtension = $this->getMockForAbstractClass(ExtensionInterface::class);
|
||||
|
||||
$app = $this->getApp(['get', 'tagged']);
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('get')
|
||||
->with('twig.environment')
|
||||
->willReturn($twig);
|
||||
$app->expects($this->once())
|
||||
->method('tagged')
|
||||
->with('twig.extension')
|
||||
->willReturn([$firsExtension, $secondExtension]);
|
||||
|
||||
$twig->expects($this->exactly(2))
|
||||
->method('addExtension')
|
||||
->withConsecutive($firsExtension, $secondExtension);
|
||||
|
||||
$serviceProvider = new TwigServiceProvider($app);
|
||||
$serviceProvider->boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\TwigServiceProvider::registerTwigEngine
|
||||
*/
|
||||
public function testRegisterTWigEngine()
|
||||
{
|
||||
/** @var TwigEngine|MockObject $htmlEngine */
|
||||
$twigEngine = $this->createMock(TwigEngine::class);
|
||||
/** @var TwigLoader|MockObject $twigLoader */
|
||||
$twigLoader = $this->createMock(TwigLoader::class);
|
||||
/** @var Twig|MockObject $twig */
|
||||
$twig = $this->createMock(Twig::class);
|
||||
|
||||
$app = $this->getApp(['make', 'instance', 'tag', 'get']);
|
||||
|
||||
$viewsPath = __DIR__ . '/Stub';
|
||||
|
||||
$app->expects($this->exactly(3))
|
||||
->method('make')
|
||||
->withConsecutive(
|
||||
[TwigLoader::class, ['paths' => $viewsPath]],
|
||||
[Twig::class],
|
||||
[TwigEngine::class]
|
||||
)->willReturnOnConsecutiveCalls(
|
||||
$twigLoader,
|
||||
$twig,
|
||||
$twigEngine
|
||||
);
|
||||
|
||||
$app->expects($this->exactly(6))
|
||||
->method('instance')
|
||||
->withConsecutive(
|
||||
[TwigLoader::class, $twigLoader],
|
||||
[TwigLoaderInterface::class, $twigLoader],
|
||||
['twig.loader', $twigLoader],
|
||||
[Twig::class, $twig],
|
||||
['twig.environment', $twig],
|
||||
['renderer.twigEngine', $twigEngine]
|
||||
);
|
||||
|
||||
$app->expects($this->once())
|
||||
->method('get')
|
||||
->with('path.views')
|
||||
->willReturn($viewsPath);
|
||||
|
||||
$this->setExpects($app, 'tag', ['renderer.twigEngine', ['renderer.engine']]);
|
||||
|
||||
$serviceProvider = new TwigServiceProvider($app);
|
||||
$this->setExtensionsTo($serviceProvider, []);
|
||||
|
||||
$serviceProvider->register();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TwigServiceProvider $serviceProvider
|
||||
* @param array $extensions
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function setExtensionsTo($serviceProvider, $extensions)
|
||||
{
|
||||
$reflection = new Reflection(get_class($serviceProvider));
|
||||
|
||||
$property = $reflection->getProperty('extensions');
|
||||
$property->setAccessible(true);
|
||||
|
||||
$property->setValue($serviceProvider, $extensions);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue