From 0927683926c172219f3cf401e3c1b4eabf19b71f Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Tue, 7 Apr 2020 17:54:18 +0200 Subject: [PATCH] Migrate dashboard part to be compatible with v10.4 10.4 introduced breaking changes for dashboard widgets. The necessary changes to stay compatible are done within this commit. No need anymore to configure widget through PHP, instead DI is used. Instead only PHP to provide data is used. --- .../NewestPageviews.php} | 67 +++---- .../PageviewsPerDay.php} | 117 ++++++----- .../PageviewsPerPage.php} | 64 +++--- Classes/Dashboard/Widgets/SettingsFactory.php | 56 ------ Configuration/Backend/DashboardWidgets.yaml | 67 +++++++ Configuration/Services.yaml | 74 +------ .../Provider/NewestPageviewsTest.php | 185 ++++++++++++++++++ 7 files changed, 392 insertions(+), 238 deletions(-) rename Classes/Dashboard/{Widgets/NewestPageviewsList.php => Provider/NewestPageviews.php} (55%) rename Classes/Dashboard/{Widgets/PageViewsBar.php => Provider/PageviewsPerDay.php} (60%) rename Classes/Dashboard/{Widgets/PageViewsPerPageDoughnut.php => Provider/PageviewsPerPage.php} (66%) delete mode 100644 Classes/Dashboard/Widgets/SettingsFactory.php create mode 100644 Configuration/Backend/DashboardWidgets.yaml create mode 100644 Tests/Unit/Dashboard/Provider/NewestPageviewsTest.php diff --git a/Classes/Dashboard/Widgets/NewestPageviewsList.php b/Classes/Dashboard/Provider/NewestPageviews.php similarity index 55% rename from Classes/Dashboard/Widgets/NewestPageviewsList.php rename to Classes/Dashboard/Provider/NewestPageviews.php index b2c2d07..4350a42 100644 --- a/Classes/Dashboard/Widgets/NewestPageviewsList.php +++ b/Classes/Dashboard/Provider/NewestPageviews.php @@ -1,6 +1,6 @@ @@ -21,67 +21,57 @@ namespace DanielSiepmann\Tracking\Dashboard\Widgets; * 02110-1301, USA. */ -use DanielSiepmann\Tracking\Extension; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Query\QueryBuilder; -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Dashboard\Widgets\AbstractListWidget; +use TYPO3\CMS\Dashboard\Widgets\Interfaces\ListDataProviderInterface; -class NewestPageviewsList extends AbstractListWidget +class NewestPageviews implements ListDataProviderInterface { - protected $title = Extension::LANGUAGE_PATH . ':dashboard.widgets.newestPageviewsList.title'; - - protected $description = Extension::LANGUAGE_PATH . ':dashboard.widgets.newestPageviewsList.description'; - - protected $width = 2; - - protected $height = 4; - /** * @var QueryBuilder */ - protected $queryBuilder; + private $queryBuilder; /** - * @var \ArrayObject + * @var int */ - private $settings; + private $maxResults; + + /** + * @var array + */ + private $blackListedPages; public function __construct( - string $identifier, QueryBuilder $queryBuilder, - \ArrayObject $settings + int $maxResults = 6, + array $blackListedPages = [] ) { - parent::__construct($identifier); - $this->queryBuilder = $queryBuilder; - $this->settings = $settings; + $this->maxResults = $maxResults; + $this->blackListedPages = $blackListedPages; } - public function renderWidgetContent(): string + public function getItems(): array { - $this->generateItems(); - return parent::renderWidgetContent(); - } + $preparedItems = []; - protected function generateItems(): void - { $constraints = []; - if (count($this->settings['blackListedPages'])) { + if (count($this->blackListedPages)) { $constraints[] = $this->queryBuilder->expr()->notIn( 'tx_tracking_pageview.pid', $this->queryBuilder->createNamedParameter( - $this->settings['blackListedPages'], + $this->blackListedPages, Connection::PARAM_INT_ARRAY ) ); } $this->queryBuilder - ->select('*') + ->select('url', 'user_agent') ->from('tx_tracking_pageview') ->orderBy('crdate', 'desc') - ->setMaxResults($this->settings['maxResults']); + ->setMaxResults($this->maxResults); if ($constraints !== []) { $this->queryBuilder->where(... $constraints); @@ -89,14 +79,13 @@ class NewestPageviewsList extends AbstractListWidget $items = $this->queryBuilder->execute()->fetchAll(); foreach ($items as $item) { - $this->items[] = [ - 'link' => $item['url'], - 'title' => sprintf( - '%s - %s', - $item['url'], - $item['user_agent'] - ), - ]; + $preparedItems[] = sprintf( + '%s - %s', + $item['url'], + $item['user_agent'] + ); } + + return $preparedItems; } } diff --git a/Classes/Dashboard/Widgets/PageViewsBar.php b/Classes/Dashboard/Provider/PageviewsPerDay.php similarity index 60% rename from Classes/Dashboard/Widgets/PageViewsBar.php rename to Classes/Dashboard/Provider/PageviewsPerDay.php index dd8831c..34dfda1 100644 --- a/Classes/Dashboard/Widgets/PageViewsBar.php +++ b/Classes/Dashboard/Provider/PageviewsPerDay.php @@ -1,6 +1,6 @@ @@ -24,52 +24,63 @@ namespace DanielSiepmann\Tracking\Dashboard\Widgets; use DanielSiepmann\Tracking\Extension; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Query\QueryBuilder; -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Dashboard\Widgets\AbstractBarChartWidget; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Dashboard\WidgetApi; +use TYPO3\CMS\Dashboard\Widgets\Interfaces\ChartDataProviderInterface; -class PageViewsBar extends AbstractBarChartWidget +class PageviewsPerDay implements ChartDataProviderInterface { - protected $title = Extension::LANGUAGE_PATH . ':dashboard.widgets.pageViewsBar.title'; - - protected $description = Extension::LANGUAGE_PATH . ':dashboard.widgets.pageViewsBar.description'; - - protected $width = 2; - - protected $height = 4; + /** + * @var LanguageService + */ + private $languageService; /** * @var QueryBuilder */ - protected $queryBuilder; + private $queryBuilder; /** - * @var \ArrayObject + * @var int */ - private $settings; + private $days; + + /** + * @var array + */ + private $blackListedPages; + + /** + * @var string + */ + private $dateFormat; public function __construct( - string $identifier, + LanguageService $languageService, QueryBuilder $queryBuilder, - \ArrayObject $settings + int $days = 31, + array $blackListedPages = [], + string $dateFormat = 'Y-m-d' ) { - parent::__construct($identifier); - $this->queryBuilder = $queryBuilder; - $this->settings = $settings; + $this->days = $days; + $this->languageService = $languageService; + $this->blackListedPages = $blackListedPages; + $this->dateFormat = $dateFormat; } - protected function prepareChartData(): void + public function getChartData(): array { - list($labels, $data) = $this->calculateDataForLastDays((int) $this->settings['periodInDays']); + list($labels, $data) = $this->calculateData(); - $this->chartData = [ + return [ 'labels' => $labels, 'datasets' => [ [ - 'label' => $this->getLanguageService()->sL( - 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:widgets.pageViewsBar.chart.dataSet.0' + 'label' => $this->languageService->sL( + Extension::LANGUAGE_PATH . 'widgets.pageViewsBar.chart.dataSet.0' ), - 'backgroundColor' => $this->chartColors[0], + 'backgroundColor' => WidgetApi::getDefaultChartColors()[0], 'border' => 0, 'data' => $data ] @@ -77,18 +88,42 @@ class PageViewsBar extends AbstractBarChartWidget ]; } - protected function getPageViewsInPeriod(int $start, int $end): int + private function calculateData(): array + { + $labels = []; + $data = []; + + for ($daysBefore = $this->days; $daysBefore >= 0; $daysBefore--) { + $timeForLabel = strtotime('-' . $daysBefore . ' day'); + $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); + } + + return [ + $labels, + $data, + ]; + } + + private function getPageviewsInPeriod(int $start, int $end): int { $constraints = [ $this->queryBuilder->expr()->gte('crdate', $start), $this->queryBuilder->expr()->lte('crdate', $end), ]; - if (count($this->settings['blackListedPages'])) { + if (count($this->blackListedPages)) { $constraints[] = $this->queryBuilder->expr()->notIn( 'tx_tracking_pageview.pid', $this->queryBuilder->createNamedParameter( - $this->settings['blackListedPages'], + $this->blackListedPages, Connection::PARAM_INT_ARRAY ) ); @@ -101,30 +136,4 @@ class PageViewsBar extends AbstractBarChartWidget ->execute() ->fetchColumn(); } - - protected function calculateDataForLastDays(int $days): array - { - $labels = []; - $data = []; - - $format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] ?: 'Y-m-d'; - - for ($daysBefore = $days; $daysBefore >= 0; $daysBefore--) { - $timeForLabel = strtotime('-' . $daysBefore . ' day'); - $startPeriod = strtotime('-' . $daysBefore . ' day 0:00:00'); - $endPeriod = strtotime('-' . $daysBefore . ' day 23:59:59'); - - if ($timeForLabel === false || $startPeriod === false || $endPeriod === false) { - continue; - } - - $labels[] = date($format, $timeForLabel); - $data[] = $this->getPageViewsInPeriod($startPeriod, $endPeriod); - } - - return [ - $labels, - $data, - ]; - } } diff --git a/Classes/Dashboard/Widgets/PageViewsPerPageDoughnut.php b/Classes/Dashboard/Provider/PageviewsPerPage.php similarity index 66% rename from Classes/Dashboard/Widgets/PageViewsPerPageDoughnut.php rename to Classes/Dashboard/Provider/PageviewsPerPage.php index 46d6ec2..e8b72d1 100644 --- a/Classes/Dashboard/Widgets/PageViewsPerPageDoughnut.php +++ b/Classes/Dashboard/Provider/PageviewsPerPage.php @@ -1,6 +1,6 @@ @@ -25,64 +25,78 @@ use DanielSiepmann\Tracking\Extension; use Doctrine\DBAL\ParameterType; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\Query\QueryBuilder; -use TYPO3\CMS\Dashboard\Widgets\AbstractDoughnutChartWidget; +use TYPO3\CMS\Dashboard\WidgetApi; +use TYPO3\CMS\Dashboard\Widgets\Interfaces\ChartDataProviderInterface; -class PageViewsPerPageDoughnut extends AbstractDoughnutChartWidget +class PageviewsPerPage implements ChartDataProviderInterface { - protected $title = Extension::LANGUAGE_PATH . ':dashboard.widgets.pageViewsPerPageDoughnut.title'; - - protected $description = Extension::LANGUAGE_PATH . ':dashboard.widgets.pageViewsPerPageDoughnut.description'; - /** * @var QueryBuilder */ - protected $queryBuilder; + private $queryBuilder; /** - * @var \ArrayObject + * @var int */ - private $settings; + private $days; + + /** + * @var int + */ + private $maxResults; + + /** + * @var array + */ + private $blackListedPages; public function __construct( - string $identifier, QueryBuilder $queryBuilder, - \ArrayObject $settings + int $days = 31, + int $maxResults = 6, + array $blackListedPages = [] ) { - parent::__construct($identifier); - $this->queryBuilder = $queryBuilder; - $this->settings = $settings; + $this->days = $days; + $this->blackListedPages = $blackListedPages; + $this->maxResults = $maxResults; } - protected function prepareChartData(): void + public function getChartData(): array { - list($labels, $data) = $this->getPageViewsPerPage((int) $this->settings['periodInDays']); + list($labels, $data) = $this->getPageviewsPerPage(); - $this->chartData = [ + return [ 'labels' => $labels, 'datasets' => [ [ - 'backgroundColor' => $this->chartColors, + 'backgroundColor' => WidgetApi::getDefaultChartColors(), 'data' => $data, ] ], ]; } - private function getPageViewsPerPage(int $days): array + private function getPageviewsPerPage(): array { $labels = []; $data = []; $constraints = [ - $this->queryBuilder->expr()->gte('tx_tracking_pageview.crdate', strtotime('-' . $days . ' day 0:00:00')), - $this->queryBuilder->expr()->lte('tx_tracking_pageview.crdate', time()), + $this->queryBuilder->expr()->gte( + 'tx_tracking_pageview.crdate', + strtotime('-' . $this->days . ' day 0:00:00') + ), + $this->queryBuilder->expr()->lte( + 'tx_tracking_pageview.crdate', + time() + ), ]; - if (count($this->settings['blackListedPages'])) { + if (count($this->blackListedPages)) { $constraints[] = $this->queryBuilder->expr()->notIn( 'tx_tracking_pageview.pid', $this->queryBuilder->createNamedParameter( - $this->settings['blackListedPages'], + $this->blackListedPages, Connection::PARAM_INT_ARRAY ) ); @@ -104,7 +118,7 @@ class PageViewsPerPageDoughnut extends AbstractDoughnutChartWidget ->where(... $constraints) ->groupBy('tx_tracking_pageview.pid') ->orderBy('total', 'desc') - ->setMaxResults($this->settings['maxResults']) + ->setMaxResults($this->maxResults) ->execute() ->fetchAll(); diff --git a/Classes/Dashboard/Widgets/SettingsFactory.php b/Classes/Dashboard/Widgets/SettingsFactory.php deleted file mode 100644 index 37cb84d..0000000 --- a/Classes/Dashboard/Widgets/SettingsFactory.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -class SettingsFactory -{ - /** - * @var array - */ - private $defaults = [ - 'pageViewsBar' => [ - 'periodInDays' => 31, - 'blackListedPages' => [], - 'maxResults' => 6, - ], - 'pageViewsPerPageDoughnut' => [ - 'periodInDays' => 31, - 'blackListedPages' => [], - 'maxResults' => 6, - ], - 'newestPageviewsList' => [ - 'blackListedPages' => [], - 'maxResults' => 6, - ], - ]; - - public function fromArray(string $widgetIdentifier, array $settings): \ArrayObject - { - $settingsToUse = $this->defaults[$widgetIdentifier] ?? []; - - ArrayUtility::mergeRecursiveWithOverrule($settingsToUse, $settings); - - return new \ArrayObject($settingsToUse); - } -} diff --git a/Configuration/Backend/DashboardWidgets.yaml b/Configuration/Backend/DashboardWidgets.yaml new file mode 100644 index 0000000..8c85103 --- /dev/null +++ b/Configuration/Backend/DashboardWidgets.yaml @@ -0,0 +1,67 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + DanielSiepmann\Tracking\Dashboard\: + resource: '../Classes/Dashboard/*' + + DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay: + arguments: + $queryBuilder: '@querybuilder.tx_tracking_pageview' + + dashboard.widget.danielsiepmann_tracking.pageViewsPerDay: + class: 'TYPO3\CMS\Dashboard\Widgets\BarChartWidget' + arguments: + $view: '@dashboard.views.widget' + $dataProvider: '@DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay' + tags: + - name: 'dashboard.widget' + identifier: 'pageViewsBar' + groupNames: 'tracking' + iconIdentifier: 'content-widget-chart-bar' + title: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.pageViewsBar.title' + description: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.pageViewsBar.description' + additionalCssClasses: 'dashboard-item--chart' + height: 'medium' + width: 'small' + + DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage: + arguments: + $queryBuilder: '@querybuilder.tx_tracking_pageview' + + dashboard.widget.danielsiepmann_tracking.pageViewsPerPage: + class: 'TYPO3\CMS\Dashboard\Widgets\DoughnutChartWidget' + arguments: + $view: '@dashboard.views.widget' + $dataProvider: '@DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage' + tags: + - name: 'dashboard.widget' + identifier: 'pageViewsPerPageDoughnut' + groupNames: 'tracking' + iconIdentifier: 'content-widget-chart-bar' + title: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.pageViewsPerPageDoughnut.title' + description: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.pageViewsPerPageDoughnut.description' + additionalCssClasses: 'dashboard-item--chart' + height: 'medium' + width: 'small' + + DanielSiepmann\Tracking\Dashboard\Provider\NewestPageviews: + arguments: + $queryBuilder: '@querybuilder.tx_tracking_pageview' + + dashboard.widget.danielsiepmann_tracking.newestPageviews: + class: 'TYPO3\CMS\Dashboard\Widgets\ListWidget' + arguments: + $view: '@dashboard.views.widget' + $dataProvider: '@DanielSiepmann\Tracking\Dashboard\Provider\NewestPageviews' + tags: + - name: 'dashboard.widget' + identifier: 'newestPageviewsList' + groupNames: 'tracking' + iconIdentifier: 'content-widget-list' + title: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.newestPageviewsList.title' + description: 'LLL:EXT:tracking/Resources/Private/Language/locallang.xlf:dashboard.widgets.newestPageviewsList.description' + height: 'medium' + width: 'small' diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 38d6e73..ae6fdbc 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,3 +1,6 @@ +imports: + - { resource: Backend/DashboardWidgets.yaml } + services: _defaults: autowire: true @@ -6,50 +9,28 @@ services: DanielSiepmann\Tracking\: resource: '../Classes/*' + exclude: '../Classes/Dashboard/*' - # Virtual services - - DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\PageViewsBar: - factory: - - '@DanielSiepmann\Tracking\Dashboard\Widgets\SettingsFactory' - - 'fromArray' - arguments: - $widgetIdentifier: 'pageViewsBar' - $settings: [] - DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\PageViewsPerPageDoughnut: - factory: - - '@DanielSiepmann\Tracking\Dashboard\Widgets\SettingsFactory' - - 'fromArray' - arguments: - $widgetIdentifier: 'pageViewsPerPageDoughnut' - $settings: [] - DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\NewestPageviewsList: - factory: - - '@DanielSiepmann\Tracking\Dashboard\Widgets\SettingsFactory' - - 'fromArray' - arguments: - $widgetIdentifier: 'newestPageviewsList' - $settings: [] - - DanielSiepmann\Tracking\DI\DatabaseConnection\Pageview: + dbconnection.tx_tracking_pageview: + class: 'TYPO3\CMS\Core\Database\Connection' factory: - '@TYPO3\CMS\Core\Database\ConnectionPool' - 'getConnectionForTable' arguments: - 'tx_tracking_pageview' - DanielSiepmann\Tracking\DI\QueryBuilder\PageView: + + querybuilder.tx_tracking_pageview: + class: 'TYPO3\CMS\Core\Database\Query\QueryBuilder' factory: - '@TYPO3\CMS\Core\Database\ConnectionPool' - 'getQueryBuilderForTable' arguments: - 'tx_tracking_pageview' - # Existing classes - DanielSiepmann\Tracking\Domain\Repository\Pageview: public: true arguments: - - '@DanielSiepmann\Tracking\DI\DatabaseConnection\Pageview' + - '@dbconnection.tx_tracking_pageview' DanielSiepmann\Tracking\Middleware\Pageview: public: true @@ -60,38 +41,3 @@ services: 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 "/mattermost|Slackbot|WhatsApp/") - - # Dashboard Widgets - - DanielSiepmann\Tracking\Dashboard\Widgets\PageViewsBar: - class: 'DanielSiepmann\Tracking\Dashboard\Widgets\PageViewsBar' - arguments: - $identifier: 'pageViewsBar' - $queryBuilder: '@DanielSiepmann\Tracking\DI\QueryBuilder\PageView' - $settings: '@DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\PageViewsBar' - tags: - - name: 'dashboard.widget' - identifier: 'pageViewsBar' - widgetGroups: 'tracking' - - DanielSiepmann\Tracking\Dashboard\Widgets\PageViewsPerPageDoughnut: - class: 'DanielSiepmann\Tracking\Dashboard\Widgets\PageViewsPerPageDoughnut' - arguments: - $identifier: 'pageViewsPerPageDoughnut' - $queryBuilder: '@DanielSiepmann\Tracking\DI\QueryBuilder\PageView' - $settings: '@DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\PageViewsPerPageDoughnut' - tags: - - name: 'dashboard.widget' - identifier: 'pageViewsPerPageDoughnut' - widgetGroups: 'tracking' - - DanielSiepmann\Tracking\Dashboard\Widgets\NewestPageviewsList: - class: 'DanielSiepmann\Tracking\Dashboard\Widgets\NewestPageviewsList' - arguments: - $identifier: 'newestPageviewsList' - $queryBuilder: '@DanielSiepmann\Tracking\DI\QueryBuilder\PageView' - $settings: '@DanielSiepmann\Tracking\DI\Dashboard\Widgets\Settings\NewestPageviewsList' - tags: - - name: 'dashboard.widget' - identifier: 'newestPageviewsList' - widgetGroups: 'tracking' diff --git a/Tests/Unit/Dashboard/Provider/NewestPageviewsTest.php b/Tests/Unit/Dashboard/Provider/NewestPageviewsTest.php new file mode 100644 index 0000000..178297e --- /dev/null +++ b/Tests/Unit/Dashboard/Provider/NewestPageviewsTest.php @@ -0,0 +1,185 @@ + + * + * 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 defaultsToNoBlackListedPages(): 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 respectsBlackListedPages(): 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() + ); + } +}