mirror of
https://github.com/DanielSiepmann/tracking.git
synced 2024-11-22 05:56:08 +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;
|
namespace DanielSiepmann\Tracking\Middleware;
|
||||||
|
|
||||||
|
use DanielSiepmann\Tracking\Domain\ExpressionLanguage\Factory as ExpressionFactory;
|
||||||
use DanielSiepmann\Tracking\Domain\Pageview\Factory;
|
use DanielSiepmann\Tracking\Domain\Pageview\Factory;
|
||||||
use DanielSiepmann\Tracking\Domain\Repository\Pageview as Repository;
|
use DanielSiepmann\Tracking\Domain\Repository\Pageview as Repository;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
|
||||||
use TYPO3\CMS\Core\Context\Context;
|
use TYPO3\CMS\Core\Context\Context;
|
||||||
|
|
||||||
class Pageview implements MiddlewareInterface
|
class Pageview implements MiddlewareInterface
|
||||||
|
@ -44,15 +44,25 @@ class Pageview implements MiddlewareInterface
|
||||||
*/
|
*/
|
||||||
private $context;
|
private $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExpressionFactory
|
||||||
|
*/
|
||||||
|
private $expressionFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $rule = '';
|
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->repository = $repository;
|
||||||
$this->context = $context;
|
$this->context = $context;
|
||||||
|
$this->expressionFactory = $expressionFactory;
|
||||||
$this->rule = $rule;
|
$this->rule = $rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +81,10 @@ class Pageview implements MiddlewareInterface
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
Context $context
|
Context $context
|
||||||
): bool {
|
): bool {
|
||||||
return (bool) (new ExpressionLanguage())->evaluate($this->rule, [
|
return (bool) $this->expressionFactory->create(
|
||||||
'request' => $request,
|
$this->rule,
|
||||||
'context' => $context,
|
$request,
|
||||||
]);
|
$context
|
||||||
|
)->evaluate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace DanielSiepmann\Tracking\Middleware;
|
namespace DanielSiepmann\Tracking\Middleware;
|
||||||
|
|
||||||
|
use DanielSiepmann\Tracking\Domain\ExpressionLanguage\Factory as ExpressionFactory;
|
||||||
use DanielSiepmann\Tracking\Domain\Model\RecordRule;
|
use DanielSiepmann\Tracking\Domain\Model\RecordRule;
|
||||||
use DanielSiepmann\Tracking\Domain\Recordview\Factory;
|
use DanielSiepmann\Tracking\Domain\Recordview\Factory;
|
||||||
use DanielSiepmann\Tracking\Domain\Repository\Recordview as Repository;
|
use DanielSiepmann\Tracking\Domain\Repository\Recordview as Repository;
|
||||||
|
@ -45,6 +46,11 @@ class Recordview implements MiddlewareInterface
|
||||||
*/
|
*/
|
||||||
private $context;
|
private $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExpressionFactory
|
||||||
|
*/
|
||||||
|
private $expressionFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<RecordRule>
|
* @var array<RecordRule>
|
||||||
*/
|
*/
|
||||||
|
@ -53,10 +59,12 @@ class Recordview implements MiddlewareInterface
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Repository $repository,
|
Repository $repository,
|
||||||
Context $context,
|
Context $context,
|
||||||
|
ExpressionFactory $expressionFactory,
|
||||||
array $rules
|
array $rules
|
||||||
) {
|
) {
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
$this->context = $context;
|
$this->context = $context;
|
||||||
|
$this->expressionFactory = $expressionFactory;
|
||||||
|
|
||||||
$this->rules = RecordRule::multipleFromArray($rules);
|
$this->rules = RecordRule::multipleFromArray($rules);
|
||||||
}
|
}
|
||||||
|
@ -79,13 +87,10 @@ class Recordview implements MiddlewareInterface
|
||||||
Context $context,
|
Context $context,
|
||||||
RecordRule $rule
|
RecordRule $rule
|
||||||
): bool {
|
): bool {
|
||||||
// Need silent, as expression language doens't provide a way to check for array keys
|
return (bool) $this->expressionFactory->create(
|
||||||
return @(bool) (new ExpressionLanguage())->evaluate(
|
|
||||||
$rule->getMatchesExpression(),
|
$rule->getMatchesExpression(),
|
||||||
[
|
$request,
|
||||||
'request' => $request,
|
$context
|
||||||
'context' => $context,
|
)->evaluate();
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ services:
|
||||||
$rule: >
|
$rule: >
|
||||||
not (context.getAspect("backend.user").isLoggedIn())
|
not (context.getAspect("backend.user").isLoggedIn())
|
||||||
and not (context.getAspect("frontend.preview").isPreview())
|
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 "/^TYPO3|TYPO3 linkvalidator/")
|
||||||
and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/")
|
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/")
|
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: >
|
$rule: >
|
||||||
not (context.getAspect("backend.user").isLoggedIn())
|
not (context.getAspect("backend.user").isLoggedIn())
|
||||||
and not (context.getAspect("frontend.preview").isPreview())
|
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 "/^TYPO3|TYPO3 linkvalidator/")
|
||||||
and not (request.getHeader("User-Agent")[0] matches "/^Codeception Testing/")
|
and not (request.getHeader("User-Agent")[0] matches "/^Codeception Testing/")
|
||||||
and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/")
|
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
|
request.getQueryParams()["tx_news_pi1"] && request.getQueryParams()["tx_news_pi1"]["news"] > 0
|
||||||
and not (context.getAspect("backend.user").isLoggedIn())
|
and not (context.getAspect("backend.user").isLoggedIn())
|
||||||
and not (context.getAspect("frontend.preview").isPreview())
|
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 "/^TYPO3|TYPO3 linkvalidator/")
|
||||||
and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/")
|
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 "/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/")
|
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'
|
tableName: 'tx_news_domain_model_news'
|
||||||
|
|
||||||
The first paragraph will not be explained, check out :ref:`t3coreapi:configure-dependency-injection-in-extensions` instead.
|
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' => 'Daniel Siepmann',
|
||||||
'author_email' => 'coding@daniel-siepmann.de',
|
'author_email' => 'coding@daniel-siepmann.de',
|
||||||
'author_company' => '',
|
'author_company' => '',
|
||||||
'version' => '1.2.0',
|
'version' => '1.3.0',
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
'depends' => [
|
'depends' => [
|
||||||
'core' => '',
|
'core' => '',
|
||||||
|
|
Loading…
Reference in a new issue