Add multi language support

Allow integrator to limit results in widget to certain languages.
If only one language is allowed, labels will be translated.
Otherwise default system language is used.

E.g. one record will be displayed in multiple languages, it would be
confusing to show him multiple times for each language.

Add TYPO3 extension for phpstan as many things would break within tests.

Relates: #15
This commit is contained in:
Daniel Siepmann 2020-07-30 12:22:32 +02:00
parent a387580df7
commit f3d69eed45
25 changed files with 1609 additions and 236 deletions

View file

@ -58,5 +58,8 @@ jobs:
- name: Code Quality (by PHPStan)
run: ./vendor/bin/phpstan analyse
- name: PHPUnit Tests
- name: PHPUnit Unit Tests
run: ./vendor/bin/phpunit --testdox
- name: PHPUnit Functional Tests
run: ./vendor/bin/phpunit -c Tests/Functional/phpunit.xml.dist --testdox

View file

@ -71,6 +71,7 @@ class NewestPageviews implements ListDataProviderInterface
->select('url', 'user_agent')
->from('tx_tracking_pageview')
->orderBy('crdate', 'desc')
->addOrderBy('uid', 'desc')
->setMaxResults($this->maxResults);
if ($constraints !== []) {

View file

@ -62,9 +62,9 @@ class PageviewsPerDay implements ChartDataProviderInterface
array $pagesToExclude = [],
string $dateFormat = 'Y-m-d'
) {
$this->languageService = $languageService;
$this->queryBuilder = $queryBuilder;
$this->days = $days;
$this->languageService = $languageService;
$this->pagesToExclude = $pagesToExclude;
$this->dateFormat = $dateFormat;
}
@ -98,10 +98,6 @@ class PageviewsPerDay implements ChartDataProviderInterface
$startPeriod = strtotime('-' . $daysBefore . ' day 0:00:00');
$endPeriod = strtotime('-' . $daysBefore . ' day 23:59:59');
if ($timeForLabel === false || $startPeriod === false || $endPeriod === false) {
continue;
}
$labels[] = date($this->dateFormat, $timeForLabel);
$data[] = $this->getPageviewsInPeriod($startPeriod, $endPeriod);
}

View file

@ -77,10 +77,6 @@ class PageviewsPerOperatingSystem implements ChartDataProviderInterface
'tx_tracking_pageview.crdate',
strtotime('-' . $this->days . ' day 0:00:00')
),
$this->queryBuilder->expr()->lte(
'tx_tracking_pageview.crdate',
time()
),
$this->queryBuilder->expr()->neq(
'tx_tracking_pageview.operating_system',
$this->queryBuilder->createNamedParameter('')
@ -94,6 +90,7 @@ class PageviewsPerOperatingSystem implements ChartDataProviderInterface
->where(... $constraints)
->groupBy('tx_tracking_pageview.operating_system')
->orderBy('total', 'desc')
->addOrderBy('operating_system', 'asc')
->setMaxResults($this->maxResults)
->execute()
->fetchAll();

View file

@ -23,8 +23,10 @@ namespace DanielSiepmann\Tracking\Dashboard\Provider;
use DanielSiepmann\Tracking\Extension;
use Doctrine\DBAL\ParameterType;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Dashboard\WidgetApi;
use TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface;
@ -35,6 +37,11 @@ class PageviewsPerPage implements ChartDataProviderInterface
*/
private $queryBuilder;
/**
* @var PageRepository
*/
private $pageRepository;
/**
* @var int
*/
@ -50,16 +57,25 @@ class PageviewsPerPage implements ChartDataProviderInterface
*/
private $pagesToExclude;
/**
* @var array<int>
*/
private $languageLimitation;
public function __construct(
QueryBuilder $queryBuilder,
PageRepository $pageRepository,
int $days = 31,
int $maxResults = 6,
array $pagesToExclude = []
array $pagesToExclude = [],
array $languageLimitation = []
) {
$this->queryBuilder = $queryBuilder;
$this->pageRepository = $pageRepository;
$this->days = $days;
$this->pagesToExclude = $pagesToExclude;
$this->maxResults = $maxResults;
$this->pagesToExclude = $pagesToExclude;
$this->languageLimitation = $languageLimitation;
}
public function getChartData(): array
@ -87,10 +103,6 @@ class PageviewsPerPage implements ChartDataProviderInterface
'tx_tracking_pageview.crdate',
strtotime('-' . $this->days . ' day 0:00:00')
),
$this->queryBuilder->expr()->lte(
'tx_tracking_pageview.crdate',
time()
),
];
if (count($this->pagesToExclude)) {
$constraints[] = $this->queryBuilder->expr()->notIn(
@ -102,9 +114,19 @@ class PageviewsPerPage implements ChartDataProviderInterface
);
}
if (count($this->languageLimitation)) {
$constraints[] = $this->queryBuilder->expr()->in(
'tx_tracking_pageview.sys_language_uid',
$this->queryBuilder->createNamedParameter(
$this->languageLimitation,
Connection::PARAM_INT_ARRAY
)
);
}
$result = $this->queryBuilder
->selectLiteral('count(tx_tracking_pageview.pid) as total')
->addSelect('pages.title', 'pages.uid')
->addSelect('pages.uid', 'tx_tracking_pageview.sys_language_uid')
->from('tx_tracking_pageview')
->leftJoin(
'tx_tracking_pageview',
@ -118,12 +140,13 @@ class PageviewsPerPage implements ChartDataProviderInterface
->where(... $constraints)
->groupBy('tx_tracking_pageview.pid')
->orderBy('total', 'desc')
->addOrderBy('tx_tracking_pageview.uid', 'desc')
->setMaxResults($this->maxResults)
->execute()
->fetchAll();
foreach ($result as $row) {
$labels[] = mb_strimwidth($row['title'], 0, 25, '…');
$labels[] = $this->getRecordTitle($row['uid'], $row['sys_language_uid']);
$data[] = $row['total'];
}
@ -132,4 +155,14 @@ class PageviewsPerPage implements ChartDataProviderInterface
$data,
];
}
private function getRecordTitle(int $uid, int $sysLanguageUid): string
{
$record = BackendUtility::getRecord('pages', $uid);
if ($sysLanguageUid > 0 && count($this->languageLimitation) === 1 && $record !== null) {
$record = $this->pageRepository->getRecordOverlay('pages', $record, $sysLanguageUid);
}
return BackendUtility::getRecordTitle('pages', $record, true);
}
}

View file

@ -24,12 +24,14 @@ namespace DanielSiepmann\Tracking\Dashboard\Provider;
use DanielSiepmann\Tracking\Extension;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Statement;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Dashboard\WidgetApi;
use TYPO3\CMS\Dashboard\Widgets\ChartDataProviderInterface;
@ -40,6 +42,11 @@ class Recordviews implements ChartDataProviderInterface
*/
private $connectionPool;
/**
* @var PageRepository
*/
private $pageRepository;
/**
* @var QueryBuilder
*/
@ -60,6 +67,11 @@ class Recordviews implements ChartDataProviderInterface
*/
private $pagesToExclude;
/**
* @var array<int>
*/
private $languageLimitation;
/**
* @var array
*/
@ -72,17 +84,21 @@ class Recordviews implements ChartDataProviderInterface
public function __construct(
ConnectionPool $connectionPool,
PageRepository $pageRepository,
QueryBuilder $queryBuilder,
int $days = 31,
int $maxResults = 6,
array $pagesToExclude = [],
array $languageLimitation = [],
array $recordTableLimitation = [],
array $recordTypeLimitation = []
) {
$this->connectionPool = $connectionPool;
$this->pageRepository = $pageRepository;
$this->queryBuilder = $queryBuilder;
$this->days = $days;
$this->pagesToExclude = $pagesToExclude;
$this->languageLimitation = $languageLimitation;
$this->maxResults = $maxResults;
$this->recordTableLimitation = $recordTableLimitation;
$this->recordTypeLimitation = $recordTypeLimitation;
@ -109,7 +125,11 @@ class Recordviews implements ChartDataProviderInterface
$data = [];
foreach ($this->getRecordviewsRecords() as $recordview) {
$record = $this->getRecord($recordview['record_uid'], $recordview['record_table_name']);
$record = $this->getRecord(
$recordview['record_uid'],
$recordview['record_table_name'],
$recordview['sys_language_uid']
);
if (
$this->recordTypeLimitation !== []
@ -134,11 +154,7 @@ class Recordviews implements ChartDataProviderInterface
$this->queryBuilder->expr()->gte(
'tx_tracking_recordview.crdate',
strtotime('-' . $this->days . ' day 0:00:00')
),
$this->queryBuilder->expr()->lte(
'tx_tracking_recordview.crdate',
time()
),
)
];
if (count($this->pagesToExclude)) {
@ -151,6 +167,16 @@ class Recordviews implements ChartDataProviderInterface
);
}
if (count($this->languageLimitation)) {
$constraints[] = $this->queryBuilder->expr()->in(
'tx_tracking_recordview.sys_language_uid',
$this->queryBuilder->createNamedParameter(
$this->languageLimitation,
Connection::PARAM_INT_ARRAY
)
);
}
if (count($this->recordTableLimitation)) {
$constraints[] = $this->queryBuilder->expr()->in(
'tx_tracking_recordview.record_table_name',
@ -163,11 +189,12 @@ class Recordviews implements ChartDataProviderInterface
$result = $this->queryBuilder
->selectLiteral('count(record) as total')
->addSelect('record_uid', 'record_table_name')
->addSelect('record_uid', 'record_table_name', 'sys_language_uid')
->from('tx_tracking_recordview')
->where(... $constraints)
->groupBy('record')
->orderBy('total', 'desc')
->addOrderBy('uid', 'desc')
->setMaxResults($this->maxResults)
->execute();
@ -176,31 +203,20 @@ class Recordviews implements ChartDataProviderInterface
}
}
private function getRecord(int $recordUid, string $recordTable): array
{
$titlefield = $GLOBALS['TCA'][$recordTable]['ctrl']['label'];
$recordTypeField = $GLOBALS['TCA'][$recordTable]['ctrl']['type'] ?? '';
private function getRecord(
int $uid,
string $table,
int $sysLanguageUid
): array {
$recordTypeField = $GLOBALS['TCA'][$table]['ctrl']['type'] ?? '';
$queryBuilder = $this->connectionPool->getQueryBuilderForTable($recordTable);
$queryBuilder->getRestrictions()
->removeByType(StartTimeRestriction::class)
->removeByType(EndTimeRestriction::class)
->removeByType(HiddenRestriction::class)
;
$queryBuilder->select($titlefield)
->from($recordTable)
->where('uid = ' . $recordUid);
if ($recordTypeField !== '') {
$queryBuilder->addSelect($recordTypeField);
$record = BackendUtility::getRecord($table, $uid);
if ($sysLanguageUid > 0 && count($this->languageLimitation) === 1 && $record !== null) {
$record = $this->pageRepository->getRecordOverlay($table, $record, $sysLanguageUid);
}
$record = $queryBuilder->execute()->fetch();
return [
'title' => $record[$titlefield],
'title' => BackendUtility::getRecordTitle($table, $record, true),
'type' => $record[$recordTypeField] ?? '',
];
}

View file

@ -24,7 +24,6 @@ Default widget configuration.
DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay:
arguments:
$queryBuilder: '@querybuilder.tx_tracking_pageview'
$blackListedPages: [1, 11, 38]
$pagesToExclude: [1, 11, 38]
dashboard.widget.danielsiepmann.tracking.pageViewsPerDay:

View file

@ -66,3 +66,13 @@ Options
This becomes handy if certain pages are called in order to show specific records.
In those cases the pages will be called very often but don't provide much benefit and can be excluded.
Use this in combination with :ref:`recordview` to show the records instead.
.. option:: $languageLimitation
Array of ``sys_language_uid``'s to include.
Defaults to empty array, all languages are shown.
Allows to limit results to specific lanuages.
All entries tracked when visiting page with this language are shown.
If multiple languages are shown, default system language labels are used.
If only a single lanugage is allowed, record labels are translated to that language.

View file

@ -101,3 +101,13 @@ Options
Using this option offers a way to limit records e.g. to specific types of news or
address records.
.. option:: $languageLimitation
Array of ``sys_language_uid``'s to include.
Defaults to empty array, all languages are shown.
Allows to limit results to specific lanuages.
All entries tracked when visiting page with this language are shown.
If multiple languages are shown, default system language labels are used.
If only a single lanugage is allowed, record labels are translated to that language.

View file

@ -0,0 +1,96 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Command;
/*
* 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\Command\UpdateDataCommand;
use Symfony\Component\Console\Tester\CommandTester;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Command\UpdateDataCommand
*/
class UpdateDataCommandTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
protected $pathsToLinkInTestInstance = [
'typo3conf/ext/tracking/Tests/Functional/Fixtures/sites' => 'typo3conf/sites',
];
/**
* @test
*/
public function updatesAllEntriesWithMissingOperatingSystem(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml');
$subject = GeneralUtility::makeInstance(UpdateDataCommand::class);
$tester = new CommandTester($subject);
$tester->execute([], ['capture_stderr_separately' => true]);
static::assertSame(0, $tester->getStatusCode());
$records = $this->getAllRecords('tx_tracking_pageview');
static::assertCount(2, $records);
static::assertSame('Linux', $records[0]['operating_system']);
static::assertSame('Android', $records[1]['operating_system']);
}
/**
* @test
*/
public function doesNotChangeExistingOperatingSystem(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml');
$subject = GeneralUtility::makeInstance(UpdateDataCommand::class);
$tester = new CommandTester($subject);
$tester->execute([], ['capture_stderr_separately' => true]);
static::assertSame(0, $tester->getStatusCode());
$records = $this->getAllRecords('tx_tracking_pageview');
static::assertCount(2, $records);
static::assertSame('Linux', $records[0]['operating_system']);
static::assertSame('Android', $records[1]['operating_system']);
}
/**
* @test
*/
public function doesNothingIfNoRecordExists(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$subject = GeneralUtility::makeInstance(UpdateDataCommand::class);
$tester = new CommandTester($subject);
$tester->execute([], ['capture_stderr_separately' => true]);
static::assertSame(0, $tester->getStatusCode());
$records = $this->getAllRecords('tx_tracking_pageview');
static::assertCount(0, $records);
}
}

View file

@ -0,0 +1,123 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider;
/*
* 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\Dashboard\Provider\NewestPageviews;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\NewestPageviews
*/
class NewestPageviewsTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
/**
* @test
*/
public function returnsRecentSixPageviews(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'url' => 'Url ' . $i,
'user_agent' => 'User-Agent ' . $i,
'crdate' => $i,
]);
}
$subject = new NewestPageviews(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview')
);
static::assertSame([
'Url 10 - User-Agent 10',
'Url 9 - User-Agent 9',
'Url 8 - User-Agent 8',
'Url 7 - User-Agent 7',
'Url 6 - User-Agent 6',
'Url 5 - User-Agent 5',
], $subject->getItems());
}
/**
* @test
*/
public function respectsMaxResults(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'url' => 'Url ' . $i,
'user_agent' => 'User-Agent ' . $i,
'crdate' => $i,
]);
}
$subject = new NewestPageviews(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
2
);
static::assertSame([
'Url 10 - User-Agent 10',
'Url 9 - User-Agent 9',
], $subject->getItems());
}
/**
* @test
*/
public function respectsPagesToExclude(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'url' => 'Url ' . $i,
'user_agent' => 'User-Agent ' . $i,
'crdate' => $i,
]);
}
$subject = new NewestPageviews(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
6,
[9]
);
static::assertSame([
'Url 10 - User-Agent 10',
'Url 8 - User-Agent 8',
'Url 7 - User-Agent 7',
'Url 6 - User-Agent 6',
'Url 5 - User-Agent 5',
'Url 4 - User-Agent 4',
], $subject->getItems());
}
}

View file

@ -0,0 +1,146 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider;
/*
* 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\Dashboard\Provider\PageviewsPerDay;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay
*/
class PageviewsPerDayTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
/**
* @test
*/
public function listsResultsForLast31DaysByDefault(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => strtotime('-' . $i . ' days'),
]);
}
$subject = new PageviewsPerDay(
GeneralUtility::makeInstance(LanguageService::class),
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview')
);
$result = $subject->getChartData();
static::assertCount(32, $result['labels']);
static::assertCount(32, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedNumberOfDays(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => strtotime('-' . $i . ' days'),
]);
}
$subject = new PageviewsPerDay(
GeneralUtility::makeInstance(LanguageService::class),
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
3
);
$result = $subject->getChartData();
static::assertCount(4, $result['labels']);
static::assertSame([
1,
1,
1,
0,
], $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedExcludedPages(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => strtotime('-' . $i . ' days'),
]);
}
$subject = new PageviewsPerDay(
GeneralUtility::makeInstance(LanguageService::class),
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
3,
[2]
);
$result = $subject->getChartData();
static::assertCount(4, $result['labels']);
static::assertSame([
1,
0,
1,
0,
], $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedDateFormat(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$subject = new PageviewsPerDay(
GeneralUtility::makeInstance(LanguageService::class),
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
1,
[],
'd.m.Y'
);
$result = $subject->getChartData();
static::assertSame([
date('d.m.Y', strtotime('-1 day')),
date('d.m.Y'),
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
}

View file

@ -0,0 +1,175 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider;
/*
* 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\Dashboard\Provider\PageviewsPerOperatingSystem;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerOperatingSystem
*/
class PageviewsPerOperatingSystemTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
/**
* @test
*/
public function listsSixResultsForLast31DaysByDefault(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'operating_system' => 'System ' . $i,
'crdate' => time(),
]);
}
$subject = new PageviewsPerOperatingSystem(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview')
);
$result = $subject->getChartData();
static::assertSame([
'System 1',
'System 10',
'System 2',
'System 3',
'System 4',
'System 5',
], $result['labels']);
static::assertCount(6, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedOrdering(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'operating_system' => 'System 1',
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'operating_system' => 'System 2',
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'operating_system' => 'System 3',
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'operating_system' => 'System 2',
'crdate' => time(),
]);
$subject = new PageviewsPerOperatingSystem(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview')
);
$result = $subject->getChartData();
static::assertSame([
'System 2',
'System 1',
'System 3',
], $result['labels']);
static::assertCount(3, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedNumberOfDays(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'operating_system' => 'System 1',
'crdate' => strtotime('-3 days'),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'operating_system' => 'System 2',
'crdate' => strtotime('-2 days'),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'operating_system' => 'System 3',
'crdate' => strtotime('-1 days'),
]);
$subject = new PageviewsPerOperatingSystem(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
2
);
$result = $subject->getChartData();
static::assertSame([
'System 2',
'System 3',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedMaxResults(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'operating_system' => 'System ' . $i,
'crdate' => time(),
]);
}
$subject = new PageviewsPerOperatingSystem(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
31,
4
);
$result = $subject->getChartData();
static::assertSame([
'System 1',
'System 10',
'System 2',
'System 3',
], $result['labels']);
static::assertCount(4, $result['datasets'][0]['data']);
}
}

View file

@ -0,0 +1,299 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider;
/*
* 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\Dashboard\Provider\PageviewsPerPage;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage
*/
class PageviewsPerPageTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
/**
* @test
*/
public function listsSixResultsForLast31DaysByDefault(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => time(),
]);
}
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class)
);
$result = $subject->getChartData();
static::assertSame([
'Page 10',
'Page 9',
'Page 8',
'Page 7',
'Page 6',
'Page 5',
], $result['labels']);
static::assertCount(6, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedOrdering(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'crdate' => time(),
]);
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class)
);
$result = $subject->getChartData();
static::assertSame([
'Page 2',
'Page 3',
'Page 1',
], $result['labels']);
static::assertCount(3, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedNumberOfDays(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'crdate' => strtotime('-3 days'),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'crdate' => strtotime('-2 days'),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'crdate' => strtotime('-1 days'),
]);
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class),
2
);
$result = $subject->getChartData();
static::assertSame([
'Page 3',
'Page 2',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedMaxResults(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => time(),
]);
}
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class),
31,
4
);
$result = $subject->getChartData();
static::assertSame([
'Page 10',
'Page 9',
'Page 8',
'Page 7',
], $result['labels']);
static::assertCount(4, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedExcludedPages(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_pageview', [
'pid' => $i,
'crdate' => time(),
]);
}
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class),
31,
6,
[1,2,3,4,5,6]
);
$result = $subject->getChartData();
static::assertSame([
'Page 10',
'Page 9',
'Page 8',
'Page 7',
], $result['labels']);
static::assertCount(4, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function localizedRecordTitlesIfLimitedToSingleLanguage(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'sys_language_uid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'sys_language_uid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'crdate' => time(),
]);
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class),
31,
6,
[],
[1]
);
$result = $subject->getChartData();
static::assertSame([
'Page 2',
'Seite 1',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function defaultLanguageTitleIsUsedIfMultipleLanguagesAreAllowed(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/Pages.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview');
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 1,
'sys_language_uid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 2,
'sys_language_uid' => 1,
'crdate' => time(),
]);
$connection->insert('tx_tracking_pageview', [
'pid' => 3,
'crdate' => time(),
]);
$subject = new PageviewsPerPage(
GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'),
GeneralUtility::makeInstance(PageRepository::class),
31,
6,
[],
[1, '0']
);
$result = $subject->getChartData();
static::assertSame([
'Page 2',
'Page 1',
'Page 3',
], $result['labels']);
static::assertCount(3, $result['datasets'][0]['data']);
}
}

View file

@ -0,0 +1,437 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider;
/*
* 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\Dashboard\Provider\Recordviews;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\Recordviews
*/
class RecordviewsTest extends TestCase
{
protected $testExtensionsToLoad = [
'typo3conf/ext/tracking',
];
/**
* @test
*/
public function listsSixResultsForLast31DaysByDefault(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_' . $i,
'record_uid' => $i,
'record_table_name' => 'sys_category',
]);
}
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview')
);
$result = $subject->getChartData();
static::assertSame([
'Category 10',
'Category 9',
'Category 8',
'Category 7',
'Category 6',
'Category 5',
], $result['labels']);
static::assertCount(6, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedOrdering(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_2',
'record_uid' => 2,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_3',
'record_uid' => 3,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_2',
'record_uid' => 2,
'record_table_name' => 'sys_category',
]);
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
2
);
$result = $subject->getChartData();
static::assertSame([
'Category 2',
'Category 3',
'Category 1',
], $result['labels']);
static::assertCount(3, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedNumberOfDays(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
$connection->insert('tx_tracking_recordview', [
'crdate' => strtotime('-3 days'),
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => strtotime('-2 days'),
'record' => 'sys_category_2',
'record_uid' => 2,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => strtotime('-1 day'),
'record' => 'sys_category_3',
'record_uid' => 3,
'record_table_name' => 'sys_category',
]);
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
2
);
$result = $subject->getChartData();
static::assertSame([
'Category 3',
'Category 2',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedMaxResults(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_' . $i,
'record_uid' => $i,
'record_table_name' => 'sys_category',
]);
}
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
2
);
$result = $subject->getChartData();
static::assertSame([
'Category 10',
'Category 9',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectedExcludedPages(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
for ($i = 1; $i <= 10; $i++) {
$connection->insert('tx_tracking_recordview', [
'pid' => $i,
'crdate' => time(),
'record' => 'sys_category_' . $i,
'record_uid' => $i,
'record_table_name' => 'sys_category',
]);
}
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
6,
[1,2,3,4,5]
);
$result = $subject->getChartData();
static::assertSame([
'Category 10',
'Category 9',
'Category 8',
'Category 7',
'Category 6',
], $result['labels']);
static::assertCount(5, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectLimitesTables(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
for ($i = 1; $i <= 3; $i++) {
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'sys_category_' . $i,
'record_uid' => $i,
'record_table_name' => 'sys_category',
]);
}
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'tt_content_1',
'record_uid' => 1,
'record_table_name' => 'tt_content',
]);
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
6,
[],
[],
['sys_category']
);
$result = $subject->getChartData();
static::assertSame([
'Category 3',
'Category 2',
'Category 1',
], $result['labels']);
static::assertCount(3, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function respectsLimitedTypes(): void
{
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
for ($i = 1; $i <= 3; $i++) {
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'record' => 'tt_content_' . $i,
'record_uid' => $i,
'record_table_name' => 'tt_content',
]);
$connection->insert('tt_content', [
'uid' => $i,
'CType' => $i,
'header' => 'Content element ' . $i,
]);
}
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
6,
[],
[],
[],
['1',2]
);
$result = $subject->getChartData();
static::assertSame([
'Content element 2',
'Content element 1',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function localizedRecordTitlesIfLimitedToSingleLanguage(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 0,
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 1,
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 1,
'record' => 'sys_category_2',
'record_uid' => 2,
'record_table_name' => 'sys_category',
]);
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
6,
[],
[1],
[],
[]
);
$result = $subject->getChartData();
static::assertSame([
'Category 2',
'Kategorie 1',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
/**
* @test
*/
public function defaultLanguageTitleIsUsedIfMultipleLanguagesAreAllowed(): void
{
$this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/SysCategories.xml');
$connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_recordview');
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 0,
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 1,
'record' => 'sys_category_1',
'record_uid' => 1,
'record_table_name' => 'sys_category',
]);
$connection->insert('tx_tracking_recordview', [
'crdate' => time(),
'sys_language_uid' => 1,
'record' => 'sys_category_2',
'record_uid' => 2,
'record_table_name' => 'sys_category',
]);
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
/* @var ConnectionPool $connectionPool */
$subject = new Recordviews(
$connectionPool,
GeneralUtility::makeInstance(PageRepository::class),
$connectionPool->getQueryBuilderForTable('tx_tracking_recordview'),
31,
6,
[],
[1, 0],
[],
[]
);
$result = $subject->getChartData();
static::assertSame([
'Category 1',
'Category 2',
], $result['labels']);
static::assertCount(2, $result['datasets'][0]['data']);
}
}

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<pages>
<pid>1</pid>
<uid>1</uid>
<title>Page 1</title>
</pages>
<pages>
<pid>1</pid>
<uid>11</uid>
<title>Seite 1</title>
<l10n_parent>1</l10n_parent>
<sys_language_uid>1</sys_language_uid>
</pages>
<pages>
<pid>1</pid>
<uid>2</uid>
<title>Page 2</title>
</pages>
<pages>
<pid>1</pid>
<uid>3</uid>
<title>Page 3</title>
</pages>
<pages>
<pid>1</pid>
<uid>4</uid>
<title>Page 4</title>
</pages>
<pages>
<pid>1</pid>
<uid>5</uid>
<title>Page 5</title>
</pages>
<pages>
<pid>1</pid>
<uid>6</uid>
<title>Page 6</title>
</pages>
<pages>
<pid>1</pid>
<uid>7</uid>
<title>Page 7</title>
</pages>
<pages>
<pid>1</pid>
<uid>8</uid>
<title>Page 8</title>
</pages>
<pages>
<pid>1</pid>
<uid>9</uid>
<title>Page 9</title>
</pages>
<pages>
<pid>1</pid>
<uid>10</uid>
<title>Page 10</title>
</pages>
</dataset>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<sys_category>
<uid>1</uid>
<title>Category 1</title>
</sys_category>
<sys_category>
<uid>11</uid>
<title>Kategorie 1</title>
<l10n_parent>1</l10n_parent>
<sys_language_uid>1</sys_language_uid>
</sys_category>
<sys_category>
<uid>2</uid>
<title>Category 2</title>
</sys_category>
<sys_category>
<uid>3</uid>
<title>Category 3</title>
</sys_category>
<sys_category>
<uid>4</uid>
<title>Category 4</title>
</sys_category>
<sys_category>
<uid>5</uid>
<title>Category 5</title>
</sys_category>
<sys_category>
<uid>6</uid>
<title>Category 6</title>
</sys_category>
<sys_category>
<uid>7</uid>
<title>Category 7</title>
</sys_category>
<sys_category>
<uid>8</uid>
<title>Category 8</title>
</sys_category>
<sys_category>
<uid>9</uid>
<title>Category 9</title>
</sys_category>
<sys_category>
<uid>10</uid>
<title>Category 10</title>
</sys_category>
</dataset>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<pages>
<pid>0</pid>
<uid>1</uid>
</pages>
<tx_tracking_pageview>
<pid>1</pid>
<uid>1</uid>
<url>https://example.com/path</url>
<user_agent>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36</user_agent>
<operating_system></operating_system>
</tx_tracking_pageview>
<tx_tracking_pageview>
<pid>1</pid>
<uid>2</uid>
<url>https://example.com/path</url>
<user_agent>Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001)</user_agent>
<operating_system></operating_system>
</tx_tracking_pageview>
</dataset>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<pages>
<pid>0</pid>
<uid>1</uid>
</pages>
<tx_tracking_pageview>
<pid>1</pid>
<uid>1</uid>
<url>https://example.com/path</url>
<user_agent>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36</user_agent>
<operating_system>Linux</operating_system>
</tx_tracking_pageview>
<tx_tracking_pageview>
<pid>1</pid>
<uid>2</uid>
<url>https://example.com/path</url>
<user_agent>Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001)</user_agent>
<operating_system>Android</operating_system>
</tx_tracking_pageview>
</dataset>

View file

@ -0,0 +1,16 @@
base: 'https://example.com'
languages:
-
title: English
enabled: true
languageId: '0'
base: /
typo3Language: default
locale: en_US.utf8
iso-639-1: en
navigationTitle: English
hreflang: en-us
direction: ltr
flag: us
websiteTitle: ''
rootPageId: 1

View file

@ -0,0 +1,32 @@
<phpunit
backupGlobals="true"
backupStaticAttributes="false"
bootstrap="../../vendor/typo3/testing-framework/Resources/Core/Build/FunctionalTestsBootstrap.php"
colors="true"
convertErrorsToExceptions="false"
convertWarningsToExceptions="false"
forceCoversAnnotation="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
verbose="false">
<testsuites>
<testsuite name="functional-tests">
<directory>.</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../Classes/Command</directory>
<directory suffix=".php">../../Classes/Dashboard</directory>
</whitelist>
</filter>
<php>
<env name="typo3DatabaseDriver" value="pdo_sqlite"/>
</php>
</phpunit>

View file

@ -1,185 +0,0 @@
<?php
namespace DanielSiepmann\Tracking\Tests\Unit\Dashboard\Provider;
/*
* 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\Dashboard\Provider\NewestPageviews;
use Doctrine\DBAL\Driver\Statement;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
/**
* @covers DanielSiepmann\Tracking\Dashboard\Provider\NewestPageviews
*/
class NewestPageviewsTest extends TestCase
{
use ProphecyTrait;
/**
* @test
*/
public function defaultsToMaxResultsOf6(): void
{
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([]);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->select(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->from(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->orderBy(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->setMaxResults(6)->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->execute()->willReturn($statement->reveal());
$subject = new NewestPageviews($queryBuilder->reveal());
$subject->getItems();
}
/**
* @test
*/
public function respectsMaxResults(): void
{
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([]);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->select(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->from(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->orderBy(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->setMaxResults(1)->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->execute()->willReturn($statement->reveal());
$subject = new NewestPageviews($queryBuilder->reveal(), 1);
$subject->getItems();
}
/**
* @test
*/
public function defaultsToNoExcludedPages(): void
{
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([]);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->select(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->from(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->orderBy(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->setMaxResults(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->execute()->willReturn($statement->reveal());
$queryBuilder->where()->shouldNotBeCalled();
$subject = new NewestPageviews($queryBuilder->reveal());
$subject->getItems();
}
/**
* @test
*/
public function respectsExcludedPages(): void
{
$expressionBuilder = $this->prophesize(ExpressionBuilder::class);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([]);
$expressionBuilder->notIn(
'tx_tracking_pageview.pid',
'10, 11'
)->willReturn('tx_tracking_pageview.pid NOT IN (10, 11)')->shouldBeCalled();
$queryBuilder->createNamedParameter(
[10, 11],
Connection::PARAM_INT_ARRAY
)->willReturn('10, 11')->shouldBeCalled();
$queryBuilder->where(
'tx_tracking_pageview.pid NOT IN (10, 11)'
)->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->expr()->willReturn($expressionBuilder->reveal());
$queryBuilder->select(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->from(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->orderBy(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->setMaxResults(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->execute()->willReturn($statement->reveal());
$subject = new NewestPageviews($queryBuilder->reveal(), 6, [10, 11]);
$subject->getItems();
}
/**
* @test
*/
public function runsQueryWithExpectedValues(): void
{
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([]);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->select('url', 'user_agent')->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->from('tx_tracking_pageview')->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->orderBy('crdate', 'desc')->willReturn($queryBuilder->reveal())->shouldBeCalled();
$queryBuilder->setMaxResults(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->execute()->willReturn($statement->reveal());
$subject = new NewestPageviews($queryBuilder->reveal());
$subject->getItems();
}
/**
* @test
*/
public function returnsSimpleList(): void
{
$statement = $this->prophesize(Statement::class);
$statement->fetchAll()->willReturn([
[
'url' => 'https://example.com/path/file.html',
'user_agent' => 'Mozilla/5.0 (user agent)',
],
[
'url' => 'https://example.com/path/file2.html',
'user_agent' => 'Mozilla/5.0 (another user agent)',
],
]);
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->select(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->from(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->orderBy(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->setMaxResults(Argument::cetera())->willReturn($queryBuilder->reveal());
$queryBuilder->execute()->willReturn($statement->reveal());
$subject = new NewestPageviews($queryBuilder->reveal());
static::assertSame(
[
'https://example.com/path/file.html - Mozilla/5.0 (user agent)',
'https://example.com/path/file2.html - Mozilla/5.0 (another user agent)',
],
$subject->getItems()
);
}
}

View file

@ -35,7 +35,8 @@
"symfony/expression-language": "^5.0",
"typo3/cms-core": "^10.4",
"symfony/console": "^5.0",
"typo3/cms-dashboard": "^10.4"
"typo3/cms-dashboard": "^10.4",
"typo3/cms-backend": "^10.4"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.5",
@ -44,7 +45,9 @@
"phpstan/extension-installer": "^1.0",
"jangregor/phpstan-prophecy": "^0.6.2",
"maglnet/composer-require-checker": "^2.1",
"phpspec/prophecy-phpunit": "^2.0"
"phpspec/prophecy-phpunit": "^2.0",
"typo3/testing-framework": "^6.3",
"saschaegerer/phpstan-typo3": "^0.13.1"
},
"minimum-stability": "dev",
"prefer-stable": true,

View file

@ -3,9 +3,21 @@ parameters:
paths:
- Classes
- Tests
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false
reportUnmatchedIgnoredErrors: true
ignoreErrors:
- '#Cannot call method fetch\(\) on Doctrine\\DBAL\\Driver\\Statement\|int\.#'
- '#Cannot call method fetchAll\(\) on Doctrine\\DBAL\\Driver\\Statement\|int\.#'
- '#Cannot call method fetchColumn\(\) on Doctrine\\DBAL\\Driver\\Statement\|int\.#'
-
message: '#\$timestamp of function date expects int, int\|false given\.#'
path: Classes/Dashboard/Provider/PageviewsPerDay.php
count: 1
-
message: '#Parameter \#1 \$start of method DanielSiepmann\\Tracking\\Dashboard\\Provider\\PageviewsPerDay::getPageviewsInPeriod\(\) expects int, int\|false given\.#'
path: Classes/Dashboard/Provider/PageviewsPerDay.php
count: 1
-
message: '#Parameter \#2 \$end of method DanielSiepmann\\Tracking\\Dashboard\\Provider\\PageviewsPerDay::getPageviewsInPeriod\(\) expects int, int\|false given\.#'
path: Classes/Dashboard/Provider/PageviewsPerDay.php
count: 1

View file

@ -20,7 +20,8 @@
<filter>
<whitelist>
<directory suffix=".php">Classes</directory>
<directory suffix=".php">Classes/Domain</directory>
<directory suffix=".php">Classes/Middleware</directory>
</whitelist>
</filter>
</phpunit>