diff --git a/.github/workflows/cs-tests.yml b/.github/workflows/cs-tests.yml
new file mode 100644
index 0000000..3da9965
--- /dev/null
+++ b/.github/workflows/cs-tests.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run phpcs checks
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run phpcs checks
+ run: vendor/bin/phpcs
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..74550fc
--- /dev/null
+++ b/.github/workflows/static-analysis.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run static analysis
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run static analysis
+ run: vendor/bin/psalm --no-cache --output-format=github --show-info=false --threads=4
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
new file mode 100644
index 0000000..593bed9
--- /dev/null
+++ b/.github/workflows/unit-tests.yml
@@ -0,0 +1,46 @@
+on:
+ - push
+
+name: Run PHPUnit tests
+
+jobs:
+ mutation:
+ name: PHP ${{ matrix.php }}-${{ matrix.os }}
+
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os:
+ - ubuntu-latest
+
+ php:
+ - "8.1"
+ - "8.2"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: composer:v2, cs2pr
+ coverage: none
+
+ - name: Determine composer cache directory
+ run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV
+
+ - name: Cache dependencies installed with composer
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.COMPOSER_CACHE_DIR }}
+ key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: |
+ php${{ matrix.php }}-composer-
+ - name: Install dependencies with composer
+ run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
+
+ - name: Run PHPUnit tests
+ run: vendor/bin/phpunit --colors=always
diff --git a/.gitignore b/.gitignore
index c4a2a74..4d3fdcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
clover.xml
coveralls-upload.json
-phpunit.xml
+.phpcs-cache
+.phpunit.result.cache
# Created by .ignore support plugin (hsz.mobi)
### JetBrains template
diff --git a/README.md b/README.md
index d2918bd..83f84b3 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,11 @@
DotKernel component providing twig extensions and customizations

-
+
[](https://github.com/dotkernel/dot-twigrenderer/issues)
[](https://github.com/dotkernel/dot-twigrenderer/network)
[](https://github.com/dotkernel/dot-twigrenderer/stargazers)
-[](https://github.com/dotkernel/dot-twigrenderer/blob/3.2.0/LICENSE.md)
+[](https://github.com/dotkernel/dot-twigrenderer/blob/3.0/LICENSE.md)
+
+[](https://insight.symfony.com/projects/b9a7d75d-d00a-44a9-b1c0-aea8670681cc)
diff --git a/composer.json b/composer.json
index dd11487..7b26cd0 100644
--- a/composer.json
+++ b/composer.json
@@ -16,20 +16,21 @@
}
],
"require": {
- "php": "~7.4.0 || ~8.0.0 || ~8.1.0",
+ "php": "~8.1.0 || ~8.2.0",
"laminas/laminas-servicemanager": "^3.11",
"mezzio/mezzio-twigrenderer": "^2.9",
"laminas/laminas-view": "^2.20",
- "laminas/laminas-authentication": "^2.10"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.5",
- "squizlabs/php_codesniffer": "^3.6",
+ "laminas/laminas-authentication": "^2.10",
"dotkernel/dot-navigation": "^3.1",
"dotkernel/dot-flashmessenger": "^3.1.1",
"laminas/laminas-form": "^3.1.1",
"doctrine/doctrine-module": "^5.1",
- "mezzio/mezzio-authorization": "^1.4"
+ "dotkernel/dot-authorization": "^3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.2",
+ "laminas/laminas-coding-standard": "^2.5",
+ "vimeo/psalm": "^5.13"
},
"autoload": {
"psr-4": {
@@ -40,5 +41,22 @@
"psr-4": {
"DotTest\\Twig\\": "test/"
}
+ },
+ "config": {
+ "sort-packages": true,
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
+ },
+ "scripts": {
+ "check": [
+ "@cs-check",
+ "@test"
+ ],
+ "cs-check": "phpcs",
+ "cs-fix": "phpcbf",
+ "test": "phpunit --colors=always",
+ "test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
+ "static-analysis": "psalm --shepherd --stats"
}
}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..1efe663
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src
+ test
+
+
+
+
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..87aab12
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ ./test
+
+
+
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
new file mode 100644
index 0000000..7c53d4a
--- /dev/null
+++ b/psalm-baseline.xml
@@ -0,0 +1,9 @@
+
+
+
+
+ twig_date_converter($env, $date)
+ twig_date_converter($env, $now)
+
+
+
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000..e6f472e
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php
index b565f50..5a22162 100644
--- a/src/ConfigProvider.php
+++ b/src/ConfigProvider.php
@@ -1,11 +1,6 @@
$this->getDependencyConfig(),
-
'view_helpers' => [],
];
}
@@ -47,43 +37,37 @@ public function __invoke(): array
public function getDependencyConfig(): array
{
return [
- 'factories' => [
- HelperPluginManager::class => HelperPluginManagerFactory::class,
-
+ 'factories' => [
+ HelperPluginManager::class => HelperPluginManagerFactory::class,
AuthenticationExtension::class => AuthenticationExtensionFactory::class,
- AuthorizationExtension::class => AuthorizationExtensionFactory::class,
- NavigationExtension::class => NavigationExtensionFactory::class,
+ AuthorizationExtension::class => AuthorizationExtensionFactory::class,
+ NavigationExtension::class => NavigationExtensionFactory::class,
FlashMessengerExtension::class => FlashMessengerExtensionFactory::class,
- FormElementsExtension::class => InvokableFactory::class,
- AuthenticationService::class => AuthenticationServiceFactory::class
+ FormElementsExtension::class => InvokableFactory::class,
+ AuthenticationService::class => AuthenticationServiceFactory::class,
],
-
- 'delegators' => [
- Environment::class => [
+ 'delegators' => [
+ Environment::class => [
TwigEnvironmentDelegator::class,
],
-
FlashMessengerRenderer::class => [
LazyServiceFactory::class,
],
- NavigationRenderer::class => [
+ NavigationRenderer::class => [
LazyServiceFactory::class,
- ]
+ ],
],
-
'lazy_services' => [
'class_map' => [
- NavigationRenderer::class =>
- NavigationRenderer::class,
-
- FlashMessengerRenderer::class =>
- FlashMessengerRenderer::class,
- ]
+ NavigationRenderer::class
+ => NavigationRenderer::class,
+ FlashMessengerRenderer::class
+ => FlashMessengerRenderer::class,
+ ],
],
-
- 'aliases' => [
- 'ViewHelperManager' => HelperPluginManager::class,
- AuthenticationServiceInterface::class => AuthenticationService::class
+ 'aliases' => [
+ 'ViewHelperManager' => HelperPluginManager::class,
+ AuthenticationServiceInterface::class => AuthenticationService::class,
],
];
}
diff --git a/src/Extension/AuthenticationExtension.php b/src/Extension/AuthenticationExtension.php
index 226fffb..3831fb3 100644
--- a/src/Extension/AuthenticationExtension.php
+++ b/src/Extension/AuthenticationExtension.php
@@ -1,45 +1,28 @@
authentication = $authentication;
}
- /**
- * @return string
- */
public function getName(): string
{
return 'dot-authentication';
}
- public function getFunctions()
+ public function getFunctions(): array
{
return [
new TwigFunction('hasIdentity', [$this, 'hasIdentity']),
@@ -52,7 +35,7 @@ public function hasIdentity(): bool
return $this->authentication->hasIdentity();
}
- public function getIdentity()
+ public function getIdentity(): mixed
{
return $this->authentication->getIdentity();
}
diff --git a/src/Extension/AuthorizationExtension.php b/src/Extension/AuthorizationExtension.php
index 7881dd3..ea0112b 100644
--- a/src/Extension/AuthorizationExtension.php
+++ b/src/Extension/AuthorizationExtension.php
@@ -1,29 +1,16 @@
authorization->isGranted($permission);
}
diff --git a/src/Extension/DateExtension.php b/src/Extension/DateExtension.php
index 187dbde..27f9bd2 100644
--- a/src/Extension/DateExtension.php
+++ b/src/Extension/DateExtension.php
@@ -1,20 +1,19 @@
'year',
'm' => 'month',
@@ -24,10 +23,7 @@ class DateExtension extends AbstractExtension
's' => 'second',
];
- /**
- * @return array|TwigFilter[]
- */
- public function getFilters()
+ public function getFilters(): array
{
return [
new TwigFilter('time_diff', [$this, 'diff'], ['needs_environment' => true]),
@@ -36,19 +32,16 @@ public function getFilters()
/**
* Filters for converting dates to a time ago string like Facebook and Twitter has.
- *
- * @param Environment $env
- * @param string|\DateTime $date a string or DateTime object to convert
- * @param string|\DateTime $now A string or DateTime object to compare with.
* If none given, the current time will be used.
- *
- * @return string the converted time
*/
- public function diff(Environment $env, $date, $now = null)
- {
+ public function diff(
+ Environment $env,
+ string|DateTimeInterface|null $date,
+ string|DateTimeZone|null $now = null
+ ): string {
// Convert both dates to DateTime instances.
$date = twig_date_converter($env, $date);
- $now = twig_date_converter($env, $now);
+ $now = twig_date_converter($env, $now);
// Get the difference between the two DateTime objects.
$diff = $date->diff($now);
@@ -65,15 +58,8 @@ public function diff(Environment $env, $date, $now = null)
return '';
}
- /**
- * @param $count
- * @param $invert
- * @param $unit
- * @return string
- */
- private function getPluralizedInterval($count, $invert, $unit)
+ public function getPluralizedInterval(mixed $count, int $invert, string $unit): string
{
-
if (1 !== $count) {
$unit .= 's';
}
diff --git a/src/Extension/FlashMessengerExtension.php b/src/Extension/FlashMessengerExtension.php
index ccf1d5d..5ad70be 100644
--- a/src/Extension/FlashMessengerExtension.php
+++ b/src/Extension/FlashMessengerExtension.php
@@ -1,11 +1,6 @@
renderer = $renderer;
}
- /**
- * @return string
- */
public function getName(): string
{
return 'dot-messenger';
}
- /**
- * @return array
- */
public function getFunctions(): array
{
return [
@@ -59,29 +39,17 @@ public function getFunctions(): array
];
}
- /**
- * @param string|null $type
- * @param string $channel
- * @return string
- */
public function renderMessages(
- string $type = null,
+ ?string $type = null,
string $channel = FlashMessengerInterface::DEFAULT_CHANNEL
): string {
return $this->renderer->render($type, $channel);
}
- /**
- * @param string $partial
- * @param array $params
- * @param string|null $type
- * @param string $channel
- * @return string
- */
public function renderMessagesPartial(
string $partial,
array $params = [],
- string $type = null,
+ ?string $type = null,
string $channel = FlashMessengerInterface::DEFAULT_CHANNEL
): string {
return $this->renderer->renderPartial($partial, $params, $type, $channel);
diff --git a/src/Extension/FormElementsExtension.php b/src/Extension/FormElementsExtension.php
index 21555a5..e4b37cf 100644
--- a/src/Extension/FormElementsExtension.php
+++ b/src/Extension/FormElementsExtension.php
@@ -1,16 +1,9 @@
Button::class,
- 'Captcha' => Captcha::class,
- 'Checkbox' => Checkbox::class,
- 'Collection' => Collection::class,
- 'Color' => Color::class,
- 'Csrf' => Csrf::class,
- 'Date' => Date::class,
- 'DateSelect' => DateSelect::class,
- 'DateTime' => DateTime::class,
- 'DateTimeLocal' => DateTimeLocal::class,
+ protected array $formElements = [
+ 'Button' => Button::class,
+ 'Captcha' => Captcha::class,
+ 'Checkbox' => Checkbox::class,
+ 'Collection' => Collection::class,
+ 'Color' => Color::class,
+ 'Csrf' => Csrf::class,
+ 'Date' => Date::class,
+ 'DateSelect' => DateSelect::class,
+ 'DateTime' => DateTime::class,
+ 'DateTimeLocal' => DateTimeLocal::class,
'DateTimeSelect' => DateTimeSelect::class,
- 'Email' => Email::class,
- 'File' => File::class,
- 'Fieldset' => Fieldset::class,
- 'Hidden' => Hidden::class,
- 'Image' => Image::class,
- 'Month' => Month::class,
- 'MonthSelect' => MonthSelect::class,
- 'MultiCheckbox' => MultiCheckbox::class,
- 'Number' => Number::class,
- 'Password' => Password::class,
- 'Radio' => Radio::class,
- 'Range' => Range::class,
- 'Search' => Search::class,
- 'Select' => Select::class,
- 'Submit' => Submit::class,
- 'Tel' => Tel::class,
- 'Text' => Text::class,
- 'Textarea' => Textarea::class,
- 'Time' => Time::class,
- 'Url' => Url::class,
- 'Week' => Week::class
+ 'Email' => Email::class,
+ 'File' => File::class,
+ 'Fieldset' => Fieldset::class,
+ 'Hidden' => Hidden::class,
+ 'Image' => Image::class,
+ 'Month' => Month::class,
+ 'MonthSelect' => MonthSelect::class,
+ 'MultiCheckbox' => MultiCheckbox::class,
+ 'Number' => Number::class,
+ 'Password' => Password::class,
+ 'Radio' => Radio::class,
+ 'Range' => Range::class,
+ 'Search' => Search::class,
+ 'Select' => Select::class,
+ 'Submit' => Submit::class,
+ 'Tel' => Tel::class,
+ 'Text' => Text::class,
+ 'Textarea' => Textarea::class,
+ 'Time' => Time::class,
+ 'Url' => Url::class,
+ 'Week' => Week::class,
];
- /**
- * @return string
- */
public function getName(): string
{
return 'dot-form';
}
- /**
- * @return array
- */
public function getTests(): array
{
$tests = [];
foreach ($this->formElements as $element => $class) {
$tests[] = new TwigTest($element, function ($value) use ($class) {
- return ($value instanceof $class);
+ return $value instanceof $class;
});
}
diff --git a/src/Extension/NavigationExtension.php b/src/Extension/NavigationExtension.php
index 3269074..dca30ef 100644
--- a/src/Extension/NavigationExtension.php
+++ b/src/Extension/NavigationExtension.php
@@ -1,11 +1,6 @@
navigationRenderer = $navigationRenderer;
@@ -49,32 +33,21 @@ public function getFunctions(): array
];
}
- /**
- * @param Page $page
- * @return mixed
- */
public function htmlAttributes(Page $page): string
{
return $this->navigationRenderer->htmlAttributes($page->getAttributes());
}
- /**
- * @param string|NavigationContainer $container
- * @return string
- */
- public function renderMenu($container): string
+ public function renderMenu(NavigationContainer|string $container): string
{
return $this->navigationRenderer->render($container);
}
- /**
- * @param string|NavigationContainer $container
- * @param string $partial
- * @param array $params
- * @return string
- */
- public function renderMenuPartial($container, string $partial, array $params = []): string
- {
+ public function renderMenuPartial(
+ NavigationContainer|string $container,
+ string $partial,
+ array $params = []
+ ): string {
return $this->navigationRenderer->renderPartial($container, $partial, $params);
}
}
diff --git a/src/Extension/Translation/TransNode.php b/src/Extension/Translation/TransNode.php
index d0aaa2f..487319b 100644
--- a/src/Extension/Translation/TransNode.php
+++ b/src/Extension/Translation/TransNode.php
@@ -1,5 +1,7 @@
$body];
if (null !== $count) {
@@ -77,8 +72,7 @@ public function compile(Compiler $compiler)
if ($vars) {
$compiler
->write('echo strtr(' . $function . '(')
- ->subcompile($msg)
- ;
+ ->subcompile($msg);
if ($this->hasNode('plural')) {
$compiler
@@ -86,8 +80,7 @@ public function compile(Compiler $compiler)
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->hasNode('count') ? $this->getNode('count') : null)
- ->raw(')')
- ;
+ ->raw(')');
}
$compiler->raw('), array(');
@@ -98,15 +91,13 @@ public function compile(Compiler $compiler)
->string('%count%')
->raw(' => abs(')
->subcompile($this->hasNode('count') ? $this->getNode('count') : null)
- ->raw('), ')
- ;
+ ->raw('), ');
} else {
$compiler
->string('%' . $var->getAttribute('name') . '%')
->raw(' => ')
->subcompile($var)
- ->raw(', ')
- ;
+ ->raw(', ');
}
}
@@ -114,8 +105,7 @@ public function compile(Compiler $compiler)
} else {
$compiler
->write('echo ' . $function . '(')
- ->subcompile($msg)
- ;
+ ->subcompile($msg);
if ($this->hasNode('plural')) {
$compiler
@@ -123,20 +113,14 @@ public function compile(Compiler $compiler)
->subcompile($msg1)
->raw(', abs(')
->subcompile($this->hasNode('count') ? $this->getNode('count') : null)
- ->raw(')')
- ;
+ ->raw(')');
}
$compiler->raw(");\n");
}
}
- /**
- * @param Node $body A Twig_Node instance
- *
- * @return array
- */
- protected function compileString(Node $body)
+ protected function compileString(Node $body): array
{
if (
$body instanceof NameExpression ||
@@ -152,8 +136,8 @@ protected function compileString(Node $body)
/** @var Node $node */
foreach ($body as $node) {
- if (get_class($node) === 'Node' && $node->getNode(0) instanceof TempNameExpression) {
- $node = $node->getNode(1);
+ if ($node::class === Node::class && $node->getNode("0") instanceof TempNameExpression) {
+ $node = $node->getNode("1");
}
if ($node instanceof PrintNode) {
@@ -161,7 +145,7 @@ protected function compileString(Node $body)
while ($n instanceof FilterExpression) {
$n = $n->getNode('node');
}
- $msg .= sprintf('%%%s%%', $n->getAttribute('name'));
+ $msg .= sprintf('%%%s%%', $n->getAttribute('name'));
$vars[] = new NameExpression($n->getAttribute('name'), $n->getTemplateLine());
} else {
$msg .= $node->getAttribute('data');
@@ -176,7 +160,6 @@ protected function compileString(Node $body)
/**
* @param bool $plural Return plural or singular function to use
- *
* @return string
*/
protected function getTransFunction($plural)
diff --git a/src/Extension/Translation/TransTokenParser.php b/src/Extension/Translation/TransTokenParser.php
index 8a42db1..343e428 100644
--- a/src/Extension/Translation/TransTokenParser.php
+++ b/src/Extension/Translation/TransTokenParser.php
@@ -1,5 +1,7 @@
getLine();
$stream = $this->parser->getStream();
- $count = null;
+ $count = null;
$plural = null;
- $notes = null;
+ $notes = null;
- if (!$stream->test(Token::BLOCK_END_TYPE)) {
+ if (! $stream->test(Token::BLOCK_END_TYPE)) {
$body = $this->parser->getExpressionParser()->parseExpression();
} else {
$stream->expect(Token::BLOCK_END_TYPE);
@@ -58,38 +51,25 @@ public function parse(Token $token)
return new TransNode($body, $plural, $count, $notes, $lineno, $this->getTag());
}
- /**
- * @param Token $token
- * @return bool
- */
- public function decideForFork(Token $token)
+ public function decideForFork(Token $token): bool
{
return $token->test(['plural', 'notes', 'endtrans']);
}
- /**
- * @param Token $token
- * @return bool
- */
- public function decideForEnd(Token $token)
+ public function decideForEnd(Token $token): bool
{
return $token->test('endtrans');
}
- /**
- * @return string
- */
- public function getTag()
+ public function getTag(): string
{
return 'trans';
}
/**
- * @param Node $body
- * @param $lineno
* @throws SyntaxError
*/
- private function checkTransString(Node $body, $lineno)
+ private function checkTransString(Node $body, mixed $lineno): void
{
foreach ($body as $i => $node) {
if (
@@ -101,7 +81,7 @@ private function checkTransString(Node $body, $lineno)
}
throw new SyntaxError(
- sprintf('The text to be translated with "trans" can only contain references to simple variables'),
+ 'The text to be translated with "trans" can only contain references to simple variables',
$lineno
);
}
diff --git a/src/Extension/TranslationExtension.php b/src/Extension/TranslationExtension.php
index 6183727..23e69f1 100644
--- a/src/Extension/TranslationExtension.php
+++ b/src/Extension/TranslationExtension.php
@@ -1,29 +1,21 @@
get(AuthenticationServiceInterface::class));
+ $service = $container->has(AuthenticationServiceInterface::class) ?
+ $container->get(AuthenticationServiceInterface::class) : null;
+
+ if (! $service instanceof AuthenticationServiceInterface) {
+ throw new Exception(sprintf('Unable to find %s', AuthenticationServiceInterface::class));
+ }
+
+ return new AuthenticationExtension($service);
}
}
diff --git a/src/Factory/AuthorizationExtensionFactory.php b/src/Factory/AuthorizationExtensionFactory.php
index 34686e4..61dccf0 100644
--- a/src/Factory/AuthorizationExtensionFactory.php
+++ b/src/Factory/AuthorizationExtensionFactory.php
@@ -1,30 +1,34 @@
get(AuthorizationInterface::class));
+ $authorizationInterface = $container->has(AuthorizationInterface::class) ?
+ $container->get(AuthorizationInterface::class) : null;
+
+ if (! $authorizationInterface instanceof AuthorizationInterface) {
+ throw new Exception(sprintf('Unable to find %s', AuthorizationInterface::class));
+ }
+
+ return new AuthorizationExtension($authorizationInterface);
}
}
diff --git a/src/Factory/FlashMessengerExtensionFactory.php b/src/Factory/FlashMessengerExtensionFactory.php
index e2633be..6345635 100644
--- a/src/Factory/FlashMessengerExtensionFactory.php
+++ b/src/Factory/FlashMessengerExtensionFactory.php
@@ -1,30 +1,34 @@
get(RendererInterface::class));
+ $renderInterface = $container->has(RendererInterface::class) ?
+ $container->get(RendererInterface::class) : null;
+
+ if (! $renderInterface instanceof RendererInterface) {
+ throw new Exception(sprintf('Unable to find %s', RendererInterface::class));
+ }
+
+ return new FlashMessengerExtension($renderInterface);
}
}
diff --git a/src/Factory/NavigationExtensionFactory.php b/src/Factory/NavigationExtensionFactory.php
index 470cf02..735a804 100644
--- a/src/Factory/NavigationExtensionFactory.php
+++ b/src/Factory/NavigationExtensionFactory.php
@@ -1,31 +1,34 @@
get(RendererInterface::class);
- return new NavigationExtension($navigationMenu);
+ $renderInterface = $container->has(RendererInterface::class) ?
+ $container->get(RendererInterface::class) : null;
+
+ if (! $renderInterface instanceof RendererInterface) {
+ throw new Exception(sprintf('Unable to find %s', RendererInterface::class));
+ }
+
+ return new NavigationExtension($renderInterface);
}
}
diff --git a/src/Laminas/View/HelperPluginManagerFactory.php b/src/Laminas/View/HelperPluginManagerFactory.php
index bbf2ea8..d7eda59 100644
--- a/src/Laminas/View/HelperPluginManagerFactory.php
+++ b/src/Laminas/View/HelperPluginManagerFactory.php
@@ -1,30 +1,36 @@
get('config')['view_helpers'];
- return new HelperPluginManager($container, $config);
+ if (! $container->has('config')) {
+ throw new Exception('Unable to find config');
+ }
+
+ $config = $container->get('config');
+
+ if (! array_key_exists('view_helpers', $config)) {
+ throw new Exception('Unable to find view_helpers config');
+ }
+
+ return new HelperPluginManager($container, $config['view_helpers']);
}
}
diff --git a/src/TwigEnvironmentDelegator.php b/src/TwigEnvironmentDelegator.php
index 11ae231..a11ac14 100644
--- a/src/TwigEnvironmentDelegator.php
+++ b/src/TwigEnvironmentDelegator.php
@@ -1,11 +1,6 @@
get('ViewHelperManager');
- $zfRenderer = new PhpRenderer();
+ $zfRenderer = new PhpRenderer();
$zfRenderer->setHelperPluginManager($viewHelperManager);
$environment->registerUndefinedFunctionCallback(
function ($name) use ($viewHelperManager, $zfRenderer) {
- if (!$viewHelperManager->has($name)) {
+ if (! $viewHelperManager->has($name)) {
return false;
}
$callable = [$zfRenderer->plugin($name), '__invoke'];
- $options = ['is_safe' => ['html']];
+ $options = ['is_safe' => ['html']];
return new TwigFunction($name, $callable, $options);
}
);
diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php
new file mode 100644
index 0000000..f425e78
--- /dev/null
+++ b/test/ConfigProviderTest.php
@@ -0,0 +1,75 @@
+config = (new ConfigProvider())();
+ }
+
+ public function testHasDependencies(): void
+ {
+ $this->assertArrayHasKey('dependencies', $this->config);
+ }
+
+ public function testDependenciesHasFactories(): void
+ {
+ $this->assertArrayHasKey('factories', $this->config['dependencies']);
+ $this->assertArrayHasKey(HelperPluginManager::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(AuthenticationExtension::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(AuthorizationExtension::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(NavigationExtension::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(FlashMessengerExtension::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(FormElementsExtension::class, $this->config['dependencies']['factories']);
+ $this->assertArrayHasKey(AuthenticationService::class, $this->config['dependencies']['factories']);
+ }
+
+ public function testDependenciesHasAliases(): void
+ {
+ $this->assertArrayHasKey('aliases', $this->config['dependencies']);
+ $this->assertArrayHasKey('ViewHelperManager', $this->config['dependencies']['aliases']);
+ $this->assertArrayHasKey(AuthenticationServiceInterface::class, $this->config['dependencies']['aliases']);
+ }
+
+ public function testDependenciesHasLazyServices(): void
+ {
+ $this->assertArrayHasKey('lazy_services', $this->config['dependencies']);
+ $this->assertArrayHasKey('class_map', $this->config['dependencies']['lazy_services']);
+ $this->assertArrayHasKey(
+ NavigationRenderer::class,
+ $this->config['dependencies']['lazy_services']['class_map']
+ );
+ $this->assertArrayHasKey(
+ FlashMessengerRenderer::class,
+ $this->config['dependencies']['lazy_services']['class_map']
+ );
+ }
+
+ public function testDependenciesHasDelegators(): void
+ {
+ $this->assertArrayHasKey('delegators', $this->config['dependencies']);
+ $this->assertArrayHasKey(Environment::class, $this->config['dependencies']['delegators']);
+ $this->assertArrayHasKey(FlashMessengerRenderer::class, $this->config['dependencies']['delegators']);
+ $this->assertArrayHasKey(NavigationRenderer::class, $this->config['dependencies']['delegators']);
+ }
+}
diff --git a/test/Extension/AuthenticationExtensionTest.php b/test/Extension/AuthenticationExtensionTest.php
new file mode 100644
index 0000000..1b9e713
--- /dev/null
+++ b/test/Extension/AuthenticationExtensionTest.php
@@ -0,0 +1,37 @@
+createMock(AuthenticationServiceInterface::class);
+ $this->extension = new AuthenticationExtension($interfaceMock);
+ }
+
+ public function testCreate(): void
+ {
+ $this->assertInstanceOf(AuthenticationExtension::class, $this->extension);
+ }
+
+ public function testFunctions(): void
+ {
+ foreach ($this->extension->getFunctions() as $function) {
+ $this->assertInstanceOf(TwigFunction::class, $function);
+ }
+ }
+}
diff --git a/test/Extension/AuthorizationExtensionTest.php b/test/Extension/AuthorizationExtensionTest.php
new file mode 100644
index 0000000..3d7c88e
--- /dev/null
+++ b/test/Extension/AuthorizationExtensionTest.php
@@ -0,0 +1,37 @@
+createMock(AuthorizationInterface::class);
+ $this->extension = new AuthorizationExtension($interfaceMock);
+ }
+
+ public function testCreate(): void
+ {
+ $this->assertInstanceOf(AuthorizationExtension::class, $this->extension);
+ }
+
+ public function testFunctions(): void
+ {
+ foreach ($this->extension->getFunctions() as $function) {
+ $this->assertInstanceOf(TwigFunction::class, $function);
+ }
+ }
+}
diff --git a/test/Extension/DateExtensionTest.php b/test/Extension/DateExtensionTest.php
new file mode 100644
index 0000000..2467403
--- /dev/null
+++ b/test/Extension/DateExtensionTest.php
@@ -0,0 +1,66 @@
+extension = new DateExtension();
+ $coreExtension = new CoreExtension();
+ $this->env = $this->createMock(Environment::class);
+ $this->env->method('getExtension')->willReturn($coreExtension);
+ }
+
+ public function testFilters(): void
+ {
+ foreach ($this->extension->getFilters() as $filter) {
+ $this->assertInstanceOf(TwigFilter::class, $filter);
+ }
+ }
+
+ public function testDiffWillReturnString(): void
+ {
+ $this->assertIsString($this->extension->diff($this->env, "2023-07-31"));
+ }
+
+ public function testDiffWillReturnExceptionUnexpectedCharacters(): void
+ {
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('Unexpected character');
+ $this->extension->diff($this->env, '2023-23-3322');
+ }
+
+ public function testDiffWillReturnExceptionNotFoundMessage(): void
+ {
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('The timezone could not be found in the database');
+ $this->extension->diff($this->env, 'asdas');
+ }
+
+ public function testPluralizedInterval(): void
+ {
+ $month = 'month'; //can be any word
+ $this->assertSame('in 1 month', $this->extension->getPluralizedInterval(1, 1, $month));
+ $this->assertSame('in 2 months', $this->extension->getPluralizedInterval(2, 1, $month));
+ $this->assertSame('1 month ago', $this->extension->getPluralizedInterval(1, 0, $month));
+ $this->assertSame('2 months ago', $this->extension->getPluralizedInterval(2, 0, $month));
+ }
+}
diff --git a/test/Extension/FlashMessengerExtensionTest.php b/test/Extension/FlashMessengerExtensionTest.php
new file mode 100644
index 0000000..c40507c
--- /dev/null
+++ b/test/Extension/FlashMessengerExtensionTest.php
@@ -0,0 +1,47 @@
+createMock(RendererInterface::class);
+ $this->extension = new FlashMessengerExtension($interfaceMock);
+ }
+
+ public function testCreate(): void
+ {
+ $this->assertInstanceOf(FlashMessengerExtension::class, $this->extension);
+ }
+
+ public function testFunctions(): void
+ {
+ foreach ($this->extension->getFunctions() as $function) {
+ $this->assertInstanceOf(TwigFunction::class, $function);
+ }
+ }
+
+ public function testWillRenderMessages(): void
+ {
+ $this->assertIsString($this->extension->renderMessages());
+ }
+
+ public function testWillRenderMessagesPartial(): void
+ {
+ $this->assertIsString($this->extension->renderMessagesPartial('partial string'));
+ }
+}
diff --git a/test/Extension/FormElementsExtensionTest.php b/test/Extension/FormElementsExtensionTest.php
new file mode 100644
index 0000000..0b05487
--- /dev/null
+++ b/test/Extension/FormElementsExtensionTest.php
@@ -0,0 +1,21 @@
+getTests();
+ foreach ($twigTests as $element) {
+ $this->assertInstanceOf(TwigTest::class, $element);
+ }
+ }
+}
diff --git a/test/Extension/NavigationExtensionTest.php b/test/Extension/NavigationExtensionTest.php
new file mode 100644
index 0000000..c7ce71c
--- /dev/null
+++ b/test/Extension/NavigationExtensionTest.php
@@ -0,0 +1,55 @@
+createMock(RendererInterface::class);
+ $this->extension = new NavigationExtension($interfaceMock);
+ }
+
+ public function testCreate(): void
+ {
+ $this->assertInstanceOf(NavigationExtension::class, $this->extension);
+ }
+
+ public function testFunctions(): void
+ {
+ foreach ($this->extension->getFunctions() as $function) {
+ $this->assertInstanceOf(TwigFunction::class, $function);
+ }
+ }
+
+ public function testHtmlAttributes(): void
+ {
+ $page = new Page();
+ $this->assertIsString($this->extension->htmlAttributes($page));
+ }
+
+ public function testRenderMenu(): void
+ {
+ $this->assertIsString($this->extension->renderMenu(new NavigationContainer()));
+ }
+
+ public function testRenderMenuPartial(): void
+ {
+ $this->assertIsString($this->extension->renderMenuPartial(new NavigationContainer(), 'partial'));
+ }
+}
diff --git a/test/Extension/TranslationExtensionTest.php b/test/Extension/TranslationExtensionTest.php
new file mode 100644
index 0000000..8069675
--- /dev/null
+++ b/test/Extension/TranslationExtensionTest.php
@@ -0,0 +1,23 @@
+extension = new TranslationExtension();
+ }
+
+ public function testTokenParsersIsArray(): void
+ {
+ $this->assertIsArray($this->extension->getTokenParsers());
+ }
+}
diff --git a/test/Factory/AuthenticationExtensionFactoryTest.php b/test/Factory/AuthenticationExtensionFactoryTest.php
new file mode 100644
index 0000000..f7a8918
--- /dev/null
+++ b/test/Factory/AuthenticationExtensionFactoryTest.php
@@ -0,0 +1,68 @@
+container = $this->createMock(ContainerInterface::class);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(AuthenticationServiceInterface::class)
+ ->willReturn(false);
+ $this->expectExceptionMessage(sprintf('Unable to find %s', AuthenticationServiceInterface::class));
+ (new AuthenticationExtensionFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testWillInstantiateWithInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(AuthenticationServiceInterface::class)
+ ->willReturn(true);
+
+ $interface = $this->createMock(AuthenticationServiceInterface::class);
+ $this->container->method('get')
+ ->willReturnMap([
+ [AuthenticationServiceInterface::class, $interface],
+ ]);
+
+ $factory = (new AuthenticationExtensionFactory())($this->container);
+
+ assertInstanceOf(AuthenticationExtension::class, $factory);
+ }
+}
diff --git a/test/Factory/AuthorizationExtensionFactoryTest.php b/test/Factory/AuthorizationExtensionFactoryTest.php
new file mode 100644
index 0000000..49ea028
--- /dev/null
+++ b/test/Factory/AuthorizationExtensionFactoryTest.php
@@ -0,0 +1,67 @@
+container = $this->createMock(ContainerInterface::class);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(AuthorizationInterface::class)
+ ->willReturn(false);
+ $this->expectExceptionMessage(sprintf('Unable to find %s', AuthorizationInterface::class));
+ (new AuthorizationExtensionFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testWillInstantiateWithInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(AuthorizationInterface::class)
+ ->willReturn(true);
+
+ $interface = $this->createMock(AuthorizationInterface::class);
+ $this->container->method('get')
+ ->willReturnMap([
+ [AuthorizationInterface::class, $interface],
+ ]);
+
+ $factory = (new AuthorizationExtensionFactory())($this->container);
+
+ self::assertInstanceOf(AuthorizationExtension::class, $factory);
+ }
+}
diff --git a/test/Factory/FlashMessengerExtensionFactoryTest.php b/test/Factory/FlashMessengerExtensionFactoryTest.php
new file mode 100644
index 0000000..9c5449f
--- /dev/null
+++ b/test/Factory/FlashMessengerExtensionFactoryTest.php
@@ -0,0 +1,68 @@
+container = $this->createMock(ContainerInterface::class);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(RendererInterface::class)
+ ->willReturn(false);
+
+ $this->expectExceptionMessage(sprintf('Unable to find %s', RendererInterface::class));
+ (new FlashMessengerExtensionFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testWillInstantiateWithInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(RendererInterface::class)
+ ->willReturn(true);
+
+ $interface = $this->createMock(RendererInterface::class);
+ $this->container->method('get')
+ ->willReturnMap([
+ [RendererInterface::class, $interface],
+ ]);
+
+ $factory = (new FlashMessengerExtensionFactory())($this->container);
+
+ self::assertInstanceOf(FlashMessengerExtension::class, $factory);
+ }
+}
diff --git a/test/Factory/NavigationExtensionFactoryTest.php b/test/Factory/NavigationExtensionFactoryTest.php
new file mode 100644
index 0000000..06b83c8
--- /dev/null
+++ b/test/Factory/NavigationExtensionFactoryTest.php
@@ -0,0 +1,68 @@
+container = $this->createMock(ContainerInterface::class);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(RendererInterface::class)
+ ->willReturn(false);
+
+ $this->expectExceptionMessage(sprintf('Unable to find %s', RendererInterface::class));
+ (new NavigationExtensionFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ * @throws Exception
+ */
+ public function testWillInstantiateWithInterface(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with(RendererInterface::class)
+ ->willReturn(true);
+
+ $interface = $this->createMock(RendererInterface::class);
+ $this->container->method('get')
+ ->willReturnMap([
+ [RendererInterface::class, $interface],
+ ]);
+
+ $factory = (new NavigationExtensionFactory())($this->container);
+
+ self::assertInstanceOf(NavigationExtension::class, $factory);
+ }
+}
diff --git a/test/Laminas/View/HelperPluginManagerFactoryTest.php b/test/Laminas/View/HelperPluginManagerFactoryTest.php
new file mode 100644
index 0000000..9e3ceb4
--- /dev/null
+++ b/test/Laminas/View/HelperPluginManagerFactoryTest.php
@@ -0,0 +1,90 @@
+container = $this->createMock(ContainerInterface::class);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutConfig(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with('config')
+ ->willReturn(false);
+
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('Unable to find config');
+ (new HelperPluginManagerFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillNotInstantiateWithoutViewHelpers(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with('config')
+ ->willReturn(true);
+
+ $this->container->expects($this->once())
+ ->method('get')
+ ->with('config')
+ ->willReturn([
+ 'test',
+ ]);
+
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('Unable to find view_helpers config');
+ (new HelperPluginManagerFactory())($this->container);
+ }
+
+ /**
+ * @throws ContainerExceptionInterface
+ * @throws NotFoundExceptionInterface
+ */
+ public function testWillInstantiate(): void
+ {
+ $this->container->expects($this->once())
+ ->method('has')
+ ->with('config')
+ ->willReturn(true);
+
+ $this->container->expects($this->once())
+ ->method('get')
+ ->with('config')
+ ->willReturn([
+ 'view_helpers' => [],
+ ]);
+
+ $factory = (new HelperPluginManagerFactory())($this->container);
+
+ $this->assertInstanceOf(HelperPluginManager::class, $factory);
+ }
+}