mirror of
https://github.com/DanielSiepmann/tracking.git
synced 2024-12-22 16:16:10 +01:00
Allow to use expressions with PHP 8.x
Introduce new traverse function taken from TYPO3 TypoScript conditions. Relates: #86
This commit is contained in:
parent
5b4a379978
commit
39529be49a
13 changed files with 297 additions and 303 deletions
37
Classes/Domain/ExpressionLanguage/Factory.php
Normal file
37
Classes/Domain/ExpressionLanguage/Factory.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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 '';
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
32
Classes/Domain/Model/Expression.php
Normal file
32
Classes/Domain/Model/Expression.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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();
|
||||
}
|
62
Classes/Domain/Model/SymfonyExpression.php
Normal file
62
Classes/Domain/Model/SymfonyExpression.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RecordRule>
|
||||
*/
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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/")
|
||||
|
|
54
Documentation/Changelog/1.3.0.rst
Normal file
54
Documentation/Changelog/1.3.0.rst
Normal file
|
@ -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
|
|
@ -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/")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace DanielSiepmann\Tracking\Tests\Unit\Middleware;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace DanielSiepmann\Tracking\Tests\Unit\Middleware;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -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' => '',
|
||||
|
|
Loading…
Reference in a new issue