From 39529be49ab6d81e216eb46557f7caa1f6d7c938 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Fri, 16 Sep 2022 13:50:40 +0200 Subject: [PATCH] Allow to use expressions with PHP 8.x Introduce new traverse function taken from TYPO3 TypoScript conditions. Relates: #86 --- Classes/Domain/ExpressionLanguage/Factory.php | 37 ++++ .../SymfonyExpressionLanguage.php | 77 +++++++ Classes/Domain/Model/Expression.php | 32 +++ Classes/Domain/Model/SymfonyExpression.php | 62 ++++++ Classes/Middleware/Pageview.php | 25 ++- Classes/Middleware/Recordview.php | 19 +- Configuration/Services.yaml | 2 +- Documentation/Changelog/1.3.0.rst | 54 +++++ Documentation/Pageview.rst | 1 + Documentation/Recordview.rst | 3 +- Tests/Unit/Middleware/PageviewTest.php | 98 --------- Tests/Unit/Middleware/RecordviewTest.php | 188 ------------------ ext_emconf.php | 2 +- 13 files changed, 297 insertions(+), 303 deletions(-) create mode 100644 Classes/Domain/ExpressionLanguage/Factory.php create mode 100644 Classes/Domain/ExpressionLanguage/SymfonyExpressionLanguage.php create mode 100644 Classes/Domain/Model/Expression.php create mode 100644 Classes/Domain/Model/SymfonyExpression.php create mode 100644 Documentation/Changelog/1.3.0.rst delete mode 100644 Tests/Unit/Middleware/PageviewTest.php delete mode 100644 Tests/Unit/Middleware/RecordviewTest.php diff --git a/Classes/Domain/ExpressionLanguage/Factory.php b/Classes/Domain/ExpressionLanguage/Factory.php new file mode 100644 index 0000000..a30363f --- /dev/null +++ b/Classes/Domain/ExpressionLanguage/Factory.php @@ -0,0 +1,37 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace DanielSiepmann\Tracking\Domain\ExpressionLanguage; + +use DanielSiepmann\Tracking\Domain\Model\Expression; +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Core\Context\Context; + +interface Factory +{ + public function create( + string $expression, + ServerRequestInterface $request, + Context $context + ): Expression; +} diff --git a/Classes/Domain/ExpressionLanguage/SymfonyExpressionLanguage.php b/Classes/Domain/ExpressionLanguage/SymfonyExpressionLanguage.php new file mode 100644 index 0000000..1487cbe --- /dev/null +++ b/Classes/Domain/ExpressionLanguage/SymfonyExpressionLanguage.php @@ -0,0 +1,77 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace DanielSiepmann\Tracking\Domain\ExpressionLanguage; + +use DanielSiepmann\Tracking\Domain\Model\Expression; +use DanielSiepmann\Tracking\Domain\Model\SymfonyExpression; +use Psr\Http\Message\ServerRequestInterface; +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use TYPO3\CMS\Core\Context\Context; +use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException; + +class SymfonyExpressionLanguage implements Factory +{ + public function create( + string $expression, + ServerRequestInterface $request, + Context $context + ): Expression { + $language = new ExpressionLanguage(); + $this->registerTraverseFunction($language); + + return new SymfonyExpression( + $expression, + [ + 'context' => $context, + 'request' => $request, + ], + $language + ); + } + + /** + * Taken from TYPO3 Core, see: https://docs.typo3.org/m/typo3/reference-typoscript/11.5/en-us/Conditions/Index.html#traverse + */ + private function registerTraverseFunction(ExpressionLanguage $language): void + { + $language->register( + 'traverse', + static function () { + // Not implemented, we only use the evaluator + }, + static function ($arguments, $array, $path) { + if (!is_array($array) || !is_string($path) || $path === '') { + return ''; + } + try { + return ArrayUtility::getValueByPath($array, $path); + } catch (MissingArrayPathException $e) { + return ''; + } + } + ); + } +} diff --git a/Classes/Domain/Model/Expression.php b/Classes/Domain/Model/Expression.php new file mode 100644 index 0000000..2766e4f --- /dev/null +++ b/Classes/Domain/Model/Expression.php @@ -0,0 +1,32 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace DanielSiepmann\Tracking\Domain\Model; + +interface Expression +{ + /** + * @return mixed + */ + public function evaluate(); +} diff --git a/Classes/Domain/Model/SymfonyExpression.php b/Classes/Domain/Model/SymfonyExpression.php new file mode 100644 index 0000000..a659902 --- /dev/null +++ b/Classes/Domain/Model/SymfonyExpression.php @@ -0,0 +1,62 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace DanielSiepmann\Tracking\Domain\Model; + +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + +class SymfonyExpression implements Expression +{ + /** + * @var string + */ + private $expression; + + /** + * @var array + */ + private $values; + + /** + * @var ExpressionLanguage + */ + private $symfonyExpression; + + public function __construct( + string $expression, + array $values, + ExpressionLanguage $symfonyExpression + ) { + $this->expression = $expression; + $this->values = $values; + $this->symfonyExpression = $symfonyExpression; + } + + public function evaluate() + { + return $this->symfonyExpression->evaluate( + $this->expression, + $this->values + ); + } +} diff --git a/Classes/Middleware/Pageview.php b/Classes/Middleware/Pageview.php index 658b6c1..63888fc 100644 --- a/Classes/Middleware/Pageview.php +++ b/Classes/Middleware/Pageview.php @@ -23,13 +23,13 @@ declare(strict_types=1); namespace DanielSiepmann\Tracking\Middleware; +use DanielSiepmann\Tracking\Domain\ExpressionLanguage\Factory as ExpressionFactory; use DanielSiepmann\Tracking\Domain\Pageview\Factory; use DanielSiepmann\Tracking\Domain\Repository\Pageview as Repository; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use TYPO3\CMS\Core\Context\Context; class Pageview implements MiddlewareInterface @@ -44,15 +44,25 @@ class Pageview implements MiddlewareInterface */ private $context; + /** + * @var ExpressionFactory + */ + private $expressionFactory; + /** * @var string */ private $rule = ''; - public function __construct(Repository $repository, Context $context, string $rule) - { + public function __construct( + Repository $repository, + Context $context, + ExpressionFactory $expressionFactory, + string $rule + ) { $this->repository = $repository; $this->context = $context; + $this->expressionFactory = $expressionFactory; $this->rule = $rule; } @@ -71,9 +81,10 @@ class Pageview implements MiddlewareInterface ServerRequestInterface $request, Context $context ): bool { - return (bool) (new ExpressionLanguage())->evaluate($this->rule, [ - 'request' => $request, - 'context' => $context, - ]); + return (bool) $this->expressionFactory->create( + $this->rule, + $request, + $context + )->evaluate(); } } diff --git a/Classes/Middleware/Recordview.php b/Classes/Middleware/Recordview.php index 17deff0..4449715 100644 --- a/Classes/Middleware/Recordview.php +++ b/Classes/Middleware/Recordview.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace DanielSiepmann\Tracking\Middleware; +use DanielSiepmann\Tracking\Domain\ExpressionLanguage\Factory as ExpressionFactory; use DanielSiepmann\Tracking\Domain\Model\RecordRule; use DanielSiepmann\Tracking\Domain\Recordview\Factory; use DanielSiepmann\Tracking\Domain\Repository\Recordview as Repository; @@ -45,6 +46,11 @@ class Recordview implements MiddlewareInterface */ private $context; + /** + * @var ExpressionFactory + */ + private $expressionFactory; + /** * @var array */ @@ -53,10 +59,12 @@ class Recordview implements MiddlewareInterface public function __construct( Repository $repository, Context $context, + ExpressionFactory $expressionFactory, array $rules ) { $this->repository = $repository; $this->context = $context; + $this->expressionFactory = $expressionFactory; $this->rules = RecordRule::multipleFromArray($rules); } @@ -79,13 +87,10 @@ class Recordview implements MiddlewareInterface Context $context, RecordRule $rule ): bool { - // Need silent, as expression language doens't provide a way to check for array keys - return @(bool) (new ExpressionLanguage())->evaluate( + return (bool) $this->expressionFactory->create( $rule->getMatchesExpression(), - [ - 'request' => $request, - 'context' => $context, - ] - ); + $request, + $context + )->evaluate(); } } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 1aaec24..df8bb13 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -59,7 +59,7 @@ services: $rule: > not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) - and request.getHeader("User-Agent")[0] + and traverse(request.getHeader("User-Agent"), '0') and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") and not (request.getHeader("User-Agent")[0] matches "/Googlebot|Bingbot|bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Sogou|Exabot|NextCloud-News|Feedly|XING FeedReader|CCBot|SemrushBot|SEOkicks|Twitterbot|Seekport Crawler|SemanticScholarBot|ia_archiver|PaperLiBot|TrendsmapResolver|AhrefsBot|Nuzzel/") diff --git a/Documentation/Changelog/1.3.0.rst b/Documentation/Changelog/1.3.0.rst new file mode 100644 index 0000000..be1456c --- /dev/null +++ b/Documentation/Changelog/1.3.0.rst @@ -0,0 +1,54 @@ +1.3.0 +===== + +Breaking +-------- + +Nothing + +Features +-------- + +* Introduce new ``traverse()`` function for rules. + The function is taken from TYPO3, documentation can be found here: https://docs.typo3.org/m/typo3/reference-typoscript/11.5/en-us/Conditions/Index.html#traverse + Rules provided by extension are adjusted. + + The new function allows for save array access in order to prevent issues in recent + PHP versions with undefined array keys. + + The important change was: + + .. code-block:: diff + + diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml + index 1aaec24..df8bb13 100644 + --- a/Configuration/Services.yaml + +++ b/Configuration/Services.yaml + @@ -59,7 +59,7 @@ services: + $rule: > + not (context.getAspect("backend.user").isLoggedIn()) + and not (context.getAspect("frontend.preview").isPreview()) + - and request.getHeader("User-Agent")[0] + + and traverse(request.getHeader("User-Agent"), '0') + and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") + and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") + and not (request.getHeader("User-Agent")[0] matches "/Googlebot|Bingbot|bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Sogou|Exabot|NextCloud-News|Feedly|XING FeedReader|CCBot|SemrushBot|SEOkicks|Twitterbot|Seekport Crawler|SemanticScholarBot|ia_archiver|PaperLiBot|TrendsmapResolver|AhrefsBot|Nuzzel/") + + Same for other array accesses, e.g recordUid of ``Recordview``:: + + recordUid: 'traverse(request.getQueryParams(), "tx_news_pi1", "news")' + +Fixes +----- + +Nothing + +Tasks +----- + +Nothing + +Deprecation +----------- + +Nothing diff --git a/Documentation/Pageview.rst b/Documentation/Pageview.rst index 443d007..c6393ca 100644 --- a/Documentation/Pageview.rst +++ b/Documentation/Pageview.rst @@ -43,6 +43,7 @@ Let us examine an concrete example:: $rule: > not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) + and traverse(request.getHeader("User-Agent"), '0') and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") and not (request.getHeader("User-Agent")[0] matches "/^Codeception Testing/") and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") diff --git a/Documentation/Recordview.rst b/Documentation/Recordview.rst index 6ed76e4..9a46c28 100644 --- a/Documentation/Recordview.rst +++ b/Documentation/Recordview.rst @@ -56,11 +56,12 @@ Let us examine an concrete example:: request.getQueryParams()["tx_news_pi1"] && request.getQueryParams()["tx_news_pi1"]["news"] > 0 and not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) + and traverse(request.getHeader("User-Agent"), '0') and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") and not (request.getHeader("User-Agent")[0] matches "/bot|spider|Slurp|Sogou|NextCloud-News|Feedly|XING FeedReader|SEOkicks|Seekport Crawler|ia_archiver|TrendsmapResolver|Nuzzel/") and not (request.getHeader("User-Agent")[0] matches "/mattermost|Slackbot|WhatsApp/") - recordUid: 'request.getQueryParams()["tx_news_pi1"]["news"]' + recordUid: 'traverse(request.getQueryParams(), "tx_news_pi1", "news")' tableName: 'tx_news_domain_model_news' The first paragraph will not be explained, check out :ref:`t3coreapi:configure-dependency-injection-in-extensions` instead. diff --git a/Tests/Unit/Middleware/PageviewTest.php b/Tests/Unit/Middleware/PageviewTest.php deleted file mode 100644 index b4dc388..0000000 --- a/Tests/Unit/Middleware/PageviewTest.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -use DanielSiepmann\Tracking\Domain\Model\Pageview as Model; -use DanielSiepmann\Tracking\Domain\Repository\Pageview as Repository; -use DanielSiepmann\Tracking\Middleware\Pageview; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\RequestHandlerInterface; -use TYPO3\CMS\Core\Context\Context; -use TYPO3\CMS\Core\Routing\PageArguments; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; - -/** - * @covers DanielSiepmann\Tracking\Middleware\Pageview - */ -class PageviewTest extends TestCase -{ - use ProphecyTrait; - - /** - * @test - */ - public function doesNotAddRequestIfRuleDoesNotApply(): void - { - $repository = $this->prophesize(Repository::class); - $context = $this->prophesize(Context::class); - $rule = 'false'; - - $request = $this->prophesize(ServerRequestInterface::class); - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - - $handler->handle($request->reveal())->willReturn($response->reveal()); - $repository->add()->shouldNotBeCalled(); - - $subject = new Pageview($repository->reveal(), $context->reveal(), $rule); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } - - /** - * @test - */ - public function addsPageviewToRepository(): void - { - $repository = $this->prophesize(Repository::class); - $context = $this->prophesize(Context::class); - $rule = 'true'; - - $routing = $this->prophesize(PageArguments::class); - $routing->getPageId()->willReturn(10); - $routing->getPageType()->willReturn(0); - - $language = $this->prophesize(SiteLanguage::class); - - $request = $this->prophesize(ServerRequestInterface::class); - $request->getAttribute('routing')->willReturn($routing->reveal()); - $request->getAttribute('language')->willReturn($language->reveal()); - $request->getUri()->willReturn(''); - $request->getHeader('User-Agent')->willReturn([]); - - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - - $handler->handle($request->reveal())->willReturn($response->reveal()); - $repository->add(Argument::type(Model::class))->shouldBeCalledtimes(1); - - $subject = new Pageview($repository->reveal(), $context->reveal(), $rule); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } -} diff --git a/Tests/Unit/Middleware/RecordviewTest.php b/Tests/Unit/Middleware/RecordviewTest.php deleted file mode 100644 index 3b00197..0000000 --- a/Tests/Unit/Middleware/RecordviewTest.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -use DanielSiepmann\Tracking\Domain\Model\Recordview as Model; -use DanielSiepmann\Tracking\Domain\Repository\Recordview as Repository; -use DanielSiepmann\Tracking\Middleware\Recordview; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\RequestHandlerInterface; -use TYPO3\CMS\Core\Context\Context; -use TYPO3\CMS\Core\Routing\PageArguments; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; - -/** - * @covers DanielSiepmann\Tracking\Middleware\Recordview - */ -class RecordviewTest extends TestCase -{ - use ProphecyTrait; - - /** - * @test - */ - public function proceedsWithNextHandlerIfNoRuleIsConfigured(): void - { - $repository = $this->prophesize(Repository::class); - $repository->add()->shouldNotBeCalled(); - $context = $this->prophesize(Context::class); - - $request = $this->prophesize(ServerRequestInterface::class); - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle($request->reveal())->willReturn($response); - - $subject = new Recordview($repository->reveal(), $context->reveal(), []); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } - - /** - * @test - */ - public function doesntAddViewIfRuleDoesNotMatchRequest(): void - { - $repository = $this->prophesize(Repository::class); - $repository->add()->shouldNotBeCalled(); - $context = $this->prophesize(Context::class); - - $request = $this->prophesize(ServerRequestInterface::class); - $request->getQueryParams()->willReturn([]); - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle($request->reveal())->willReturn($response); - - $subject = new Recordview($repository->reveal(), $context->reveal(), [ - 'topic' => [ - 'matches' => 'request.getQueryParams()["topic_id"] > 0', - 'recordUid' => '', - 'tableName' => '', - ], - ]); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } - - /** - * @test - */ - public function addsSingleViewIfRuleMatches(): void - { - $repository = $this->prophesize(Repository::class); - $repository->add(Argument::that(function (Model $recordview) { - return $recordview->getPageUid() === 10 - && $recordview->getRecordUid() === 10 - && $recordview->getTableName() === 'topics' - ; - }))->shouldBeCalled(); - $context = $this->prophesize(Context::class); - - $routing = $this->prophesize(PageArguments::class); - $routing->getPageId()->willReturn(10); - - $language = $this->prophesize(SiteLanguage::class); - - $request = $this->prophesize(ServerRequestInterface::class); - $request->getAttribute('routing')->willReturn($routing->reveal()); - $request->getAttribute('language')->willReturn($language->reveal()); - $request->getUri()->willReturn(''); - $request->getHeader('User-Agent')->willReturn([]); - $request->getQueryParams()->willReturn([ - 'topic_id' => '10', - ]); - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle($request->reveal())->willReturn($response); - - $subject = new Recordview($repository->reveal(), $context->reveal(), [ - 'topic' => [ - 'matches' => 'request.getQueryParams()["topic_id"] > 0', - 'recordUid' => 'request.getQueryParams()["topic_id"]', - 'tableName' => 'topics', - ], - ]); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } - - /** - * @test - */ - public function canAddMultipleViewsIfMultipleRulesApply(): void - { - $repository = $this->prophesize(Repository::class); - $repository->add(Argument::that(function (Model $recordview) { - return $recordview->getPageUid() === 10 - && $recordview->getRecordUid() === 10 - && $recordview->getTableName() === 'topics' - ; - }))->shouldBeCalled(); - $repository->add(Argument::that(function (Model $recordview) { - return $recordview->getPageUid() === 10 - && $recordview->getRecordUid() === 20 - && $recordview->getTableName() === 'news' - ; - }))->shouldBeCalled(); - $context = $this->prophesize(Context::class); - - $routing = $this->prophesize(PageArguments::class); - $routing->getPageId()->willReturn(10); - - $language = $this->prophesize(SiteLanguage::class); - - $request = $this->prophesize(ServerRequestInterface::class); - $request->getAttribute('routing')->willReturn($routing->reveal()); - $request->getAttribute('language')->willReturn($language->reveal()); - $request->getUri()->willReturn(''); - $request->getHeader('User-Agent')->willReturn([]); - $request->getQueryParams()->willReturn([ - 'topic_id' => '10', - 'news' => '20', - ]); - $response = $this->prophesize(ResponseInterface::class); - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle($request->reveal())->willReturn($response); - - $subject = new Recordview($repository->reveal(), $context->reveal(), [ - 'topic' => [ - 'matches' => 'request.getQueryParams()["topic_id"] > 0', - 'recordUid' => 'request.getQueryParams()["topic_id"]', - 'tableName' => 'topics', - ], - 'news' => [ - 'matches' => 'request.getQueryParams()["news"] > 0', - 'recordUid' => 'request.getQueryParams()["news"]', - 'tableName' => 'news', - ], - ]); - $result = $subject->process($request->reveal(), $handler->reveal()); - - static::assertInstanceOf(ResponseInterface::class, $result); - } -} diff --git a/ext_emconf.php b/ext_emconf.php index a9cfb10..500a6e7 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -11,7 +11,7 @@ $EM_CONF[$_EXTKEY] = [ 'author' => 'Daniel Siepmann', 'author_email' => 'coding@daniel-siepmann.de', 'author_company' => '', - 'version' => '1.2.0', + 'version' => '1.3.0', 'constraints' => [ 'depends' => [ 'core' => '',