Merge pull request #622 from MyIgel/controllers
AuthController (login, logout), use templating, replaced gettext, input validationmain
commit
d4d4b409b6
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Migrations;
|
||||
|
||||
use Engelsystem\Database\Migration\Migration;
|
||||
|
||||
class FixUserLanguages extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$connection = $this->schema->getConnection();
|
||||
$connection
|
||||
->table('users_settings')
|
||||
->update([
|
||||
'language' => $connection->raw('REPLACE(language, ".UTF-8", "")')
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$connection = $this->schema->getConnection();
|
||||
$connection
|
||||
->table('users_settings')
|
||||
->update([
|
||||
'language' => $connection->raw('CONCAT(language, ".UTF-8")')
|
||||
]);
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Engelsystem 2.0\n"
|
||||
"POT-Creation-Date: 2017-12-29 19:01+0100\n"
|
||||
"PO-Revision-Date: 2019-06-04 23:41+0200\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.8.11\n"
|
||||
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
|
||||
"X-Poedit-Basepath: .\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"Last-Translator: \n"
|
||||
"Language: en_US\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#~ msgid "auth.no-nickname"
|
||||
#~ msgstr "Please enter a nickname."
|
||||
|
||||
#~ msgid "auth.no-password"
|
||||
#~ msgstr "Please enter a password."
|
||||
|
||||
msgid "auth.not-found"
|
||||
msgstr "No user was found. Please try again. If you are still having problems, ask Heaven."
|
||||
|
||||
msgid "validation.password.required"
|
||||
msgstr "The password is required."
|
||||
|
||||
msgid "validation.login.required"
|
||||
msgstr "The login name is required."
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@
|
||||
{% extends "errors/default.twig" %}
|
||||
|
||||
{% block title %}{{ __("405: Method not allowed") }}{% endblock %}
|
||||
|
||||
{% block content_headline_text %}{{ __("405: Method not allowed") }}{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% macro angel() %}
|
||||
<span class="icon-icon_angel"></span>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro glyphicon(glyph) %}
|
||||
<span class="glyphicon glyphicon-{{ glyph }}"></span>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro alert(message, type) %}
|
||||
<div class="alert alert-{{ type|default('info') }}">{{ message }}</div>
|
||||
{% endmacro %}
|
@ -0,0 +1,104 @@
|
||||
{% extends "layouts/app.twig" %}
|
||||
{% import 'macros/base.twig' as m %}
|
||||
|
||||
{% block title %}{{ __('Login') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<h2>{{ __('Welcome to the %s!', [config('name') ~ m.angel() ~ (config('app_name')|upper) ])|raw }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
{% for name,date in {
|
||||
(__('Buildup starts')): config('buildup_start'),
|
||||
(__('Event starts')): config('event_start'),
|
||||
(__('Event ends')): config('event_end'),
|
||||
(__('Teardown ends')): config('teardown_end')
|
||||
} if date %}
|
||||
{% if date > date() %}
|
||||
<div class="col-sm-3 text-center hidden-xs">
|
||||
<h4>{{ name }}</h4>
|
||||
<span class="moment-countdown text-big" data-timestamp="{{ date.getTimestamp }}">%c</span>
|
||||
<small>{{ date.format(__('Y-m-d')) }}</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4">
|
||||
<div class="panel panel-primary first">
|
||||
|
||||
<div class="panel-heading">{{ m.angel }} {{ __('Login') }}</div>
|
||||
|
||||
<div class="panel-body">
|
||||
{% for message in errors|default([]) %}
|
||||
{{ m.alert(__(message), 'danger') }}
|
||||
{% endfor %}
|
||||
|
||||
<form action="" enctype="multipart/form-data" method="post">
|
||||
{{ csrf() }}
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="form_nick"
|
||||
type="text" name="login" value="" placeholder="{{ __('Nick') }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="form_password"
|
||||
type="password" name="password" value="" placeholder="{{ __('Password') }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary" type="submit" name="submit">
|
||||
{{ __('Login') }}
|
||||
</button>
|
||||
|
||||
{% if show_password_recovery|default(false) %}
|
||||
<a href="{{ url('user-password-recovery') }}" class="btn btn-default ">
|
||||
{{ __('I forgot my password') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="panel-footer">
|
||||
{{ m.glyphicon('info-sign') }} {{ __('Please note: You have to activate cookies!') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6 text-center">
|
||||
<h2>{{ __('Register') }}</h2>
|
||||
{% if has_permission_to('register') and config('registration_enabled') %}
|
||||
<p>{{ __('Please sign up, if you want to help us!') }}</p>
|
||||
<div class="form-group">
|
||||
<a href="{{ url('register') }}" class="btn btn-default">{{ __('Register') }} »</a>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ m.alert(__('Registration is disabled.'), 'danger') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 text-center">
|
||||
<h2>{{ __('What can I do?') }}</h2>
|
||||
<p>{{ __('Please read about the jobs you can do to help us.') }}</p>
|
||||
<div class="form-group">
|
||||
<a href="{{ url('angeltypes', {'action': 'about'}) }}" class="btn btn-default">
|
||||
{{ __('Teams/Job description') }} »
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Helpers\Translation;
|
||||
|
||||
use Gettext\Translator;
|
||||
|
||||
class GettextTranslator extends Translator
|
||||
{
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param string $context
|
||||
* @param string $original
|
||||
* @return string
|
||||
* @throws TranslationNotFound
|
||||
*/
|
||||
public function dpgettext($domain, $context, $original)
|
||||
{
|
||||
$this->assertHasTranslation($domain, $context, $original);
|
||||
|
||||
return parent::dpgettext($domain, $context, $original);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param string $context
|
||||
* @param string $original
|
||||
* @param string $plural
|
||||
* @param string $value
|
||||
* @return string
|
||||
* @throws TranslationNotFound
|
||||
*/
|
||||
public function dnpgettext($domain, $context, $original, $plural, $value)
|
||||
{
|
||||
$this->assertHasTranslation($domain, $context, $original);
|
||||
|
||||
return parent::dnpgettext($domain, $context, $original, $plural, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param string $context
|
||||
* @param string $original
|
||||
* @throws TranslationNotFound
|
||||
*/
|
||||
protected function assertHasTranslation($domain, $context, $original)
|
||||
{
|
||||
if ($this->getTranslation($domain, $context, $original)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new TranslationNotFound(implode('/', [$domain, $context, $original]));
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Helpers\Translation;
|
||||
|
||||
use Exception;
|
||||
|
||||
class TranslationNotFound extends Exception
|
||||
{
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Helpers\Translation;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Gettext\Translations;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
class TranslationServiceProvider extends ServiceProvider
|
||||
{
|
||||
/** @var GettextTranslator */
|
||||
protected $translators = [];
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
/** @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');
|
||||
$fallbackLocale = $config->get('fallback_locale', 'en_US');
|
||||
|
||||
$sessionLocale = $session->get('locale', $locale);
|
||||
if (isset($locales[$sessionLocale])) {
|
||||
$locale = $sessionLocale;
|
||||
}
|
||||
|
||||
$session->set('locale', $locale);
|
||||
|
||||
$translator = $this->app->make(
|
||||
Translator::class,
|
||||
[
|
||||
'locale' => $locale,
|
||||
'locales' => $locales,
|
||||
'fallbackLocale' => $fallbackLocale,
|
||||
'getTranslatorCallback' => [$this, 'getTranslator'],
|
||||
'localeChangeCallback' => [$this, 'setLocale'],
|
||||
]
|
||||
);
|
||||
$this->app->instance(Translator::class, $translator);
|
||||
$this->app->instance('translator', $translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function setLocale(string $locale): void
|
||||
{
|
||||
$locale .= '.UTF-8';
|
||||
// Set the users locale
|
||||
putenv('LC_ALL=' . $locale);
|
||||
setlocale(LC_ALL, $locale);
|
||||
|
||||
// Reset numeric formatting to allow output of floats
|
||||
putenv('LC_NUMERIC=C');
|
||||
setlocale(LC_NUMERIC, 'C');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @return GettextTranslator
|
||||
*/
|
||||
public function getTranslator(string $locale): GettextTranslator
|
||||
{
|
||||
if (!isset($this->translators[$locale])) {
|
||||
$file = $this->app->get('path.lang') . '/' . $locale . '/default.mo';
|
||||
|
||||
/** @var GettextTranslator $translator */
|
||||
$translator = $this->app->make(GettextTranslator::class);
|
||||
|
||||
/** @var Translations $translations */
|
||||
$translations = $this->app->make(Translations::class);
|
||||
$translations->addFromMoFile($file);
|
||||
|
||||
$translator->loadTranslations($translations);
|
||||
|
||||
$this->translators[$locale] = $translator;
|
||||
}
|
||||
|
||||
return $this->translators[$locale];
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?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)
|
||||
{
|
||||
// Set the users locale
|
||||
putenv('LC_ALL=' . $locale);
|
||||
setlocale(LC_ALL, $locale);
|
||||
|
||||
// Reset numeric formatting to allow output of floats
|
||||
putenv('LC_NUMERIC=C');
|
||||
setlocale(LC_NUMERIC, 'C');
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Exceptions;
|
||||
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class ValidationException extends RuntimeException
|
||||
{
|
||||
/** @var Validator */
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(
|
||||
Validator $validator,
|
||||
string $message = '',
|
||||
int $code = 0,
|
||||
Throwable $previous = null
|
||||
) {
|
||||
$this->validator = $validator;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Validator
|
||||
*/
|
||||
public function getValidator(): Validator
|
||||
{
|
||||
return $this->validator;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Rules\In as RespectIn;
|
||||
|
||||
class In extends RespectIn
|
||||
{
|
||||
/**
|
||||
* @param mixed $haystack
|
||||
* @param bool $compareIdentical
|
||||
*/
|
||||
public function __construct($haystack, $compareIdentical = false)
|
||||
{
|
||||
if (!is_array($haystack)) {
|
||||
$haystack = explode(',', $haystack);
|
||||
}
|
||||
|
||||
parent::__construct($haystack, $compareIdentical);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Validation\Rules;
|
||||
|
||||
class NotIn extends In
|
||||
{
|
||||
/**
|
||||
* @param mixed $input
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($input)
|
||||
{
|
||||
return !parent::validate($input);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Validation;
|
||||
|
||||
use Engelsystem\Http\Exceptions\ValidationException;
|
||||
use Engelsystem\Http\Request;
|
||||
|
||||
trait ValidatesRequest
|
||||
{
|
||||
/** @var Validator */
|
||||
protected $validator;
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $rules
|
||||
* @return array
|
||||
*/
|
||||
protected function validate(Request $request, array $rules)
|
||||
{
|
||||
if (!$this->validator->validate(
|
||||
(array)$request->getParsedBody(),
|
||||
$rules
|
||||
)) {
|
||||
throw new ValidationException($this->validator);
|
||||
}
|
||||
|
||||
return $this->validator->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*/
|
||||
public function setValidator(Validator $validator)
|
||||
{
|
||||
$this->validator = $validator;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Validation;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Engelsystem\Controllers\BaseController;
|
||||
|
||||
class ValidationServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$validator = $this->app->make(Validator::class);
|
||||
$this->app->instance(Validator::class, $validator);
|
||||
$this->app->instance('validator', $validator);
|
||||
|
||||
$this->app->afterResolving(function ($object, Application $app) {
|
||||
if (!$object instanceof BaseController) {
|
||||
return;
|
||||
}
|
||||
|
||||
$object->setValidator($app->get(Validator::class));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http\Validation;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Respect\Validation\Exceptions\ComponentException;
|
||||
use Respect\Validation\Validator as RespectValidator;
|
||||
|
||||
class Validator
|
||||
{
|
||||
/** @var string[] */
|
||||
protected $errors = [];
|
||||
|
||||
/** @var array */
|
||||
protected $data = [];
|
||||
|
||||
/** @var array */
|
||||
protected $mapping = [
|
||||
'accepted' => 'TrueVal',
|
||||
'int' => 'IntVal',
|
||||
'required' => 'NotEmpty',
|
||||
];
|
||||
|
||||
/** @var array */
|
||||
protected $nestedRules = ['optional', 'not'];
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($data, $rules)
|
||||
{
|
||||
$this->errors = [];
|
||||
$this->data = [];
|
||||
|
||||
foreach ($rules as $key => $values) {
|
||||
$v = new RespectValidator();
|
||||
$v->with('\\Engelsystem\\Http\\Validation\\Rules', true);
|
||||
|
||||
$value = isset($data[$key]) ? $data[$key] : null;
|
||||
$values = explode('|', $values);
|
||||
|
||||
$packing = [];
|
||||
foreach ($this->nestedRules as $rule) {
|
||||
if (in_array($rule, $values)) {
|
||||
$packing[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
$values = array_diff($values, $this->nestedRules);
|
||||
foreach ($values as $parameters) {
|
||||
$parameters = explode(':', $parameters);
|
||||
$rule = array_shift($parameters);
|
||||
$rule = Str::camel($rule);
|
||||
$rule = $this->map($rule);
|
||||
|
||||
// To allow rules nesting
|
||||
$w = $v;
|
||||
try {
|
||||
foreach (array_reverse(array_merge($packing, [$rule])) as $rule) {
|
||||
if (!in_array($rule, $this->nestedRules)) {
|
||||
call_user_func_array([$w, $rule], $parameters);
|
||||
continue;
|
||||
}
|
||||
|
||||
$w = call_user_func_array([new RespectValidator(), $rule], [$w]);
|
||||
}
|
||||
} catch (ComponentException $e) {
|
||||
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
if ($w->validate($value)) {
|
||||
$this->data[$key] = $value;
|
||||
} else {
|
||||
$this->errors[$key][] = implode('.', ['validation', $key, $this->mapBack($rule)]);
|
||||
}
|
||||
|
||||
$v->removeRules();
|
||||
}
|
||||
}
|
||||
|
||||
return empty($this->errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rule
|
||||
* @return string
|
||||
*/
|
||||
protected function map($rule)
|
||||
{
|
||||
return $this->mapping[$rule] ?? $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rule
|
||||
* @return string
|
||||
*/
|
||||
protected function mapBack($rule)
|
||||
{
|
||||
$mapping = array_flip($this->mapping);
|
||||
|
||||
return $mapping[$rule] ?? $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Renderer;
|
||||
|
||||
abstract class Engine implements EngineInterface
|
||||
{
|
||||
/** @var array */
|
||||
protected $sharedData = [];
|
||||
|
||||
/**
|
||||
* @param mixed[]|string $key
|
||||
* @param null $value
|
||||
*/
|
||||
public function share($key, $value = null)
|
||||
{
|
||||
if (!is_array($key)) {
|
||||
$key = [$key => $value];
|
||||
}
|
||||
|
||||
$this->sharedData = array_replace_recursive($this->sharedData, $key);
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
# Testing content
|
||||
msgid "foo.bar"
|
||||
msgstr "Foo Bar!"
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Helpers\Translation;
|
||||
|
||||
use Engelsystem\Helpers\Translation\GettextTranslator;
|
||||
use Engelsystem\Helpers\Translation\TranslationNotFound;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use Gettext\Translation;
|
||||
use Gettext\Translations;
|
||||
|
||||
class GettextTranslatorTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\GettextTranslator::assertHasTranslation()
|
||||
*/
|
||||
public function testNoTranslation()
|
||||
{
|
||||
$translations = $this->getTranslations();
|
||||
|
||||
$translator = new GettextTranslator();
|
||||
$translator->loadTranslations($translations);
|
||||
|
||||
$this->assertEquals('Translation!', $translator->gettext('test.value'));
|
||||
|
||||
$this->expectException(TranslationNotFound::class);
|
||||
$this->expectExceptionMessage('//foo.bar');
|
||||
|
||||
$translator->gettext('foo.bar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\GettextTranslator::dpgettext()
|
||||
*/
|
||||
public function testDpgettext()
|
||||
{
|
||||
$translations = $this->getTranslations();
|
||||
|
||||
$translator = new GettextTranslator();
|
||||
$translator->loadTranslations($translations);
|
||||
|
||||
$this->assertEquals('Translation!', $translator->dpgettext(null, null, 'test.value'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\GettextTranslator::dnpgettext()
|
||||
*/
|
||||
public function testDnpgettext()
|
||||
{
|
||||
$translations = $this->getTranslations();
|
||||
|
||||
$translator = new GettextTranslator();
|
||||
$translator->loadTranslations($translations);
|
||||
|
||||
$this->assertEquals('Translations!', $translator->dnpgettext(null, null, 'test.value', 'test.values', 2));
|
||||
}
|
||||
|
||||
protected function getTranslations(): Translations
|
||||
{
|
||||
$translations = new Translations();
|
||||
$translations[] =
|
||||
(new Translation(null, 'test.value', 'test.values'))
|
||||
->setTranslation('Translation!')
|
||||
->setPluralTranslations(['Translations!']);
|
||||
|
||||
return $translations;
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Helpers\Translation;
|
||||
|
||||
use Engelsystem\Helpers\Translation\GettextTranslator;
|
||||
use Engelsystem\Helpers\Translation\TranslationNotFound;
|
||||
use Engelsystem\Helpers\Translation\Translator;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use stdClass;
|
||||
|
||||
class TranslatorTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::__construct
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::getLocale
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::getLocales
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::hasLocale
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::setLocale
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::setLocales
|
||||
*/
|
||||
public function testInit()
|
||||
{
|
||||
$locales = ['te_ST' => 'Tests', 'fo_OO' => 'SomeFOO'];
|
||||
$locale = 'te_ST';
|
||||
|
||||
/** @var callable|MockObject $localeChange */
|
||||
$localeChange = $this->getMockBuilder(stdClass::class)
|
||||
->setMethods(['__invoke'])
|
||||
->getMock();
|
||||
$localeChange->expects($this->exactly(2))
|
||||
->method('__invoke')
|
||||
->withConsecutive(['te_ST'], ['fo_OO']);
|
||||
|
||||
$translator = new Translator($locale, 'fo_OO', function () { }, $locales, $localeChange);
|
||||
|
||||
$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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::translate
|
||||
*/
|
||||
public function testTranslate()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->getMockBuilder(Translator::class)
|
||||
->setConstructorArgs(['de_DE', 'en_US', function () { }, ['de_DE' => 'Deutsch']])
|
||||
->setMethods(['translateText'])
|
||||
->getMock();
|
||||
$translator->expects($this->exactly(2))
|
||||
->method('translateText')
|
||||
->withConsecutive(['gettext', ['Hello!'], []], ['gettext', ['My favourite number is %u!'], [3]])
|
||||
->willReturnOnConsecutiveCalls('Hallo!', 'Meine Lieblingszahl ist die 3!');
|
||||
|
||||
$return = $translator->translate('Hello!');
|
||||
$this->assertEquals('Hallo!', $return);
|
||||
|
||||
$return = $translator->translate('My favourite number is %u!', [3]);
|
||||
$this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::translatePlural
|
||||
*/
|
||||
public function testTranslatePlural()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->getMockBuilder(Translator::class)
|
||||
->setConstructorArgs(['de_DE', 'en_US', function () { }, ['de_DE' => 'Deutsch']])
|
||||
->setMethods(['translateText'])
|
||||
->getMock();
|
||||
$translator->expects($this->once())
|
||||
->method('translateText')
|
||||
->with('ngettext', ['%s apple', '%s apples', 2], [2])
|
||||
->willReturn('2 Äpfel');
|
||||
|
||||
$return = $translator->translatePlural('%s apple', '%s apples', 2, [2]);
|
||||
$this->assertEquals('2 Äpfel', $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::translatePlural
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::translateText
|
||||
* @covers \Engelsystem\Helpers\Translation\Translator::replaceText
|
||||
*/
|
||||
public function testReplaceText()
|
||||
{
|
||||
/** @var GettextTranslator|MockObject $gtt */
|
||||
$gtt = $this->createMock(GettextTranslator::class);
|
||||
/** @var callable|MockObject $getTranslator */
|
||||
$getTranslator = $this->getMockBuilder(stdClass::class)
|
||||
->setMethods(['__invoke'])
|
||||
->getMock();
|
||||
$getTranslator->expects($this->exactly(5))
|
||||
->method('__invoke')
|
||||
->withConsecutive(['te_ST'], ['fo_OO'], ['te_ST'], ['fo_OO'], ['te_ST'])
|
||||
->willReturn($gtt);
|
||||
|
||||
$i = 0;
|
||||
$gtt->expects($this->exactly(4))
|
||||
->method('gettext')
|
||||
->willReturnCallback(function () use (&$i) {
|
||||
$i++;
|
||||
if ($i != 4) {
|
||||
throw new TranslationNotFound();
|
||||
}
|
||||
|
||||
return 'Lorem %s???';
|
||||
});
|
||||
$this->setExpects($gtt, 'ngettext', ['foo.barf'], 'Lorem %s!');
|
||||
|
||||
$translator = new Translator('te_ST', 'fo_OO', $getTranslator, ['te_ST' => 'Test', 'fo_OO' => 'Foo']);
|
||||
|
||||
// No translation
|
||||
$this->assertEquals('foo.bar', $translator->translate('foo.bar'));
|
||||
|
||||
// Fallback translation
|
||||
$this->assertEquals('Lorem test2???', $translator->translate('foo.batz', ['test2']));
|
||||
|
||||
// Successful translation
|
||||
$this->assertEquals('Lorem test3!', $translator->translatePlural('foo.barf', 'foo.bar2', 3, ['test3']));
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
<?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::getLocale
|
||||
* @covers \Engelsystem\Helpers\Translator::getLocales
|
||||
* @covers \Engelsystem\Helpers\Translator::hasLocale
|
||||
* @covers \Engelsystem\Helpers\Translator::setLocale
|
||||
* @covers \Engelsystem\Helpers\Translator::setLocales
|
||||
*/
|
||||
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::replaceText
|
||||
* @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->exactly(2))
|
||||
->method('translateGettext')
|
||||
->withConsecutive(['Hello!'], ['My favourite number is %u!'])
|
||||
->willReturnOnConsecutiveCalls('Hallo!', 'Meine Lieblingszahl ist die %u!');
|
||||
|
||||
$return = $translator->translate('Hello!');
|
||||
$this->assertEquals('Hallo!', $return);
|
||||
|
||||
$return = $translator->translate('My favourite number is %u!', [3]);
|
||||
$this->assertEquals('Meine Lieblingszahl ist die 3!', $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Helpers\Translator::translatePlural
|
||||
*/
|
||||
public function testTranslatePlural()
|
||||
{
|
||||
/** @var Translator|MockObject $translator */
|
||||
$translator = $this->getMockBuilder(Translator::class)
|
||||
->setConstructorArgs(['de_DE.UTF-8', ['de_DE.UTF-8' => 'Deutsch']])
|
||||
->setMethods(['translateGettextPlural'])
|
||||
->getMock();
|
||||
$translator->expects($this->once())
|
||||
->method('translateGettextPlural')
|
||||
->with('%s apple', '%s apples', 2)
|
||||
->willReturn('2 Äpfel');
|
||||
|
||||
$return = $translator->translatePlural('%s apple', '%s apples', 2, [2]);
|
||||
$this->assertEquals('2 Äpfel', $return);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Exceptions;
|
||||
|
||||
use Engelsystem\Http\Exceptions\ValidationException;
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ValidationExceptionTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Exceptions\ValidationException::__construct
|
||||
* @covers \Engelsystem\Http\Exceptions\ValidationException::getValidator
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
/** @var Validator|MockObject $validator */
|
||||
$validator = $this->createMock(Validator::class);
|
||||
|
||||
$exception = new ValidationException($validator);
|
||||
|
||||
$this->assertEquals($validator, $exception->getValidator());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation\Rules;
|
||||
|
||||
use Engelsystem\Http\Validation\Rules\In;
|
||||
use Engelsystem\Test\Unit\TestCase;
|
||||
|
||||
class InTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Rules\In::__construct
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$rule = new In('foo,bar');
|
||||
|
||||
$this->assertEquals(['foo', 'bar'], $rule->haystack);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation\Rules;
|
||||
|
||||
use Engelsystem\Http\Validation\Rules\NotIn;
|
||||
use Engelsystem\Test\Unit\TestCase;
|
||||
|
||||
class NotInTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Rules\NotIn::validate
|
||||
*/
|
||||
public function testConstruct()
|
||||
{
|
||||
$rule = new NotIn('foo,bar');
|
||||
|
||||
$this->assertTrue($rule->validate('lorem'));
|
||||
$this->assertFalse($rule->validate('foo'));
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation\Stub;
|
||||
|
||||
use Engelsystem\Controllers\BaseController;
|
||||
use Engelsystem\Http\Request;
|
||||
|
||||
class ValidatesRequestImplementation extends BaseController
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param array $rules
|
||||
* @return array
|
||||
*/
|
||||
public function validateData(Request $request, array $rules)
|
||||
{
|
||||
return $this->validate($request, $rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasValidator()
|
||||
{
|
||||
return !is_null($this->validator);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation;
|
||||
|
||||
use Engelsystem\Http\Exceptions\ValidationException;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use Engelsystem\Test\Unit\Http\Validation\Stub\ValidatesRequestImplementation;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ValidatesRequestTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\ValidatesRequest::validate
|
||||
* @covers \Engelsystem\Http\Validation\ValidatesRequest::setValidator
|
||||
*/
|
||||
public function testValidate()
|
||||
{
|
||||
/** @var Validator|MockObject $validator */
|
||||
$validator = $this->createMock(Validator::class);
|
||||
$validator->expects($this->exactly(2))
|
||||
->method('validate')
|
||||
->withConsecutive(
|
||||
[['foo' => 'bar'], ['foo' => 'required']],
|
||||
[[], ['foo' => 'required']]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
true,
|
||||
false
|
||||
);
|
||||
$validator->expects($this->once())
|
||||
->method('getData')
|
||||
->willReturn(['foo' => 'bar']);
|
||||
|
||||
$implementation = new ValidatesRequestImplementation();
|
||||
$implementation->setValidator($validator);
|
||||
|
||||
$return = $implementation->validateData(new Request([], ['foo' => 'bar']), ['foo' => 'required']);
|
||||
|
||||
$this->assertEquals(['foo' => 'bar'], $return);
|
||||
|
||||
$this->expectException(ValidationException::class);
|
||||
$implementation->validateData(new Request([], []), ['foo' => 'required']);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Http\Validation\ValidationServiceProvider;
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use Engelsystem\Test\Unit\Http\Validation\Stub\ValidatesRequestImplementation;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use stdClass;
|
||||
|
||||
class ValidationServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\ValidationServiceProvider::register
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
$app = new Application();
|
||||
|
||||
$serviceProvider = new ValidationServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
|
||||
$this->assertTrue($app->has(Validator::class));
|
||||
$this->assertTrue($app->has('validator'));
|
||||
|
||||
/** @var ValidatesRequestImplementation $validatesRequest */
|
||||
$validatesRequest = $app->make(ValidatesRequestImplementation::class);
|
||||
$this->assertTrue($validatesRequest->hasValidator());
|
||||
|
||||
// Test afterResolving early return
|
||||
$app->make(stdClass::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http\Validation;
|
||||
|
||||
use Engelsystem\Http\Validation\Validator;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ValidatorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Validator::validate
|
||||
* @covers \Engelsystem\Http\Validation\Validator::getData
|
||||
* @covers \Engelsystem\Http\Validation\Validator::getErrors
|
||||
*/
|
||||
public function testValidate()
|
||||
{
|
||||
$val = new Validator();
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => 'bar', 'lorem' => 'on', 'dolor' => 'bla'],
|
||||
['lorem' => 'accepted']
|
||||
));
|
||||
$this->assertEquals(['lorem' => 'on'], $val->getData());
|
||||
|
||||
$this->assertFalse($val->validate(
|
||||
[],
|
||||
['lorem' => 'required|min:3']
|
||||
));
|
||||
$this->assertEquals(
|
||||
['lorem' => ['validation.lorem.required', 'validation.lorem.min']],
|
||||
$val->getErrors()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Validator::validate
|
||||
*/
|
||||
public function testValidateChaining()
|
||||
{
|
||||
$val = new Validator();
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
['lorem' => 10],
|
||||
['lorem' => 'required|min:3|max:10']
|
||||
));
|
||||
$this->assertTrue($val->validate(
|
||||
['lorem' => 3],
|
||||
['lorem' => 'required|min:3|max:10']
|
||||
));
|
||||
|
||||
$this->assertFalse($val->validate(
|
||||
['lorem' => 2],
|
||||
['lorem' => 'required|min:3|max:10']
|
||||
));
|
||||
$this->assertFalse($val->validate(
|
||||
['lorem' => 42],
|
||||
['lorem' => 'required|min:3|max:10']
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Validator::validate
|
||||
*/
|
||||
public function testValidateNotImplemented()
|
||||
{
|
||||
$val = new Validator();
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
$val->validate(
|
||||
['lorem' => 'bar'],
|
||||
['foo' => 'never_implemented']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Validator::map
|
||||
* @covers \Engelsystem\Http\Validation\Validator::mapBack
|
||||
*/
|
||||
public function testValidateMapping()
|
||||
{
|
||||
$val = new Validator();
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => 'bar'],
|
||||
['foo' => 'required']
|
||||
));
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => '0'],
|
||||
['foo' => 'int']
|
||||
));
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => 'on'],
|
||||
['foo' => 'accepted']
|
||||
));
|
||||
|
||||
$this->assertFalse($val->validate(
|
||||
[],
|
||||
['lorem' => 'required']
|
||||
));
|
||||
$this->assertEquals(
|
||||
['lorem' => ['validation.lorem.required']],
|
||||
$val->getErrors()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Http\Validation\Validator::validate
|
||||
*/
|
||||
public function testValidateNesting()
|
||||
{
|
||||
$val = new Validator();
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
[],
|
||||
['foo' => 'not|required']
|
||||
));
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => 'foo'],
|
||||
['foo' => 'not|int']
|
||||
));
|
||||
$this->assertFalse($val->validate(
|
||||
['foo' => 1],
|
||||
['foo' => 'not|int']
|
||||
));
|
||||
|
||||
$this->assertTrue($val->validate(
|
||||
[],
|
||||
['foo' => 'optional|int']
|
||||
));
|
||||
$this->assertTrue($val->validate(
|
||||
['foo' => '33'],
|
||||
['foo' => 'optional|int']
|
||||
));
|
||||
$this->assertFalse($val->validate(
|
||||
['foo' => 'T'],
|
||||
['foo' => 'optional|int']
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer;
|
||||
|
||||
use Engelsystem\Test\Unit\Renderer\Stub\EngineImplementation;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class EngineTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Renderer\Engine::share
|
||||
*/
|
||||
public function testShare()
|
||||
{
|
||||
$engine = new EngineImplementation();
|
||||
$engine->share(['foo' => ['bar' => 'baz', 'lorem' => 'ipsum']]);
|
||||
$engine->share(['foo' => ['lorem' => 'dolor']]);
|
||||
$engine->share('key', 'value');
|
||||
|
||||
$this->assertEquals(
|
||||
['foo' => ['bar' => 'baz', 'lorem' => 'dolor'], 'key' => 'value'],
|
||||
$engine->getSharedData()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Renderer\Stub;
|
||||
|
||||
use Engelsystem\Renderer\Engine;
|
||||
|
||||
class EngineImplementation extends Engine
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get(string $path, array $data = []): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function canRender(string $path): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSharedData(): array
|
||||
{
|
||||
return $this->sharedData;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue