From 5f0490f493cadbc3ebbadda3e800b1035eceeab7 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 16 Aug 2021 09:56:19 +0200 Subject: [PATCH] WIP|Add flags feature Allow each tracking record to contain arbitrary tags. Those tags are generated via an API and can be extended by foreign extensions or for individual projects. Existing operating_system was moved to this new feature. The update command allows to migrate existing records to this new feature. Those flags can be used when configuring widgets. A new flag was added bot:yes and bot:no. Bots are now tracked but flagged. That new feature allows to build fine grained reports and makes the extension way more flexible. Possible new implications: - Show visits from none bots - Show visits from bots - Show visits from specific bot - Add color to page views per page (bar chart) to color bot or none bot WIP: - Update Yaml file to work like before, no bots in widgets - Add documentation (widgets) - Add documentation (migration *.yaml) --- Classes/Command/UpdateDataCommand.php | 52 +++- Classes/Dashboard/Provider/Demand.php | 181 ++++++++++++++ Classes/Dashboard/Provider/Demand/Tag.php | 64 +++++ .../Dashboard/Provider/NewestPageviews.php | 48 +--- .../Dashboard/Provider/PageviewsPerDay.php | 59 ++--- .../Provider/PageviewsPerOperatingSystem.php | 61 +++-- .../Dashboard/Provider/PageviewsPerPage.php | 75 ++---- Classes/Dashboard/Provider/Recordviews.php | 66 ++--- Classes/Domain/Extractors/Bots.php | 88 +++++++ .../Extractors/Bots/CustomBotParser.php | 56 +++++ .../OperatingSystem.php} | 26 +- .../PageviewExtractor.php} | 14 +- .../Domain/Extractors/RecordviewExtractor.php | 37 +++ Classes/Domain/Extractors/Registry.php | 74 ++++++ Classes/Domain/Extractors/Tag.php | 57 +++++ Classes/Domain/Model/Pageview.php | 7 +- Classes/Domain/Model/Recordview.php | 21 +- Classes/Domain/Recordview/Factory.php | 22 ++ Classes/Domain/Repository/Pageview.php | 63 +++-- Classes/Domain/Repository/Recordview.php | 81 +++++- Classes/Domain/Repository/Tag.php | 119 +++++++++ Classes/Extension.php | 11 + Configuration/Bots.yaml | 18 ++ Configuration/Services.php | 40 +++ Configuration/Services.yaml | 20 +- Configuration/TCA/tx_tracking_pageview.php | 11 +- Configuration/TCA/tx_tracking_recordview.php | 19 +- Configuration/TCA/tx_tracking_tag.php | 67 +++++ Documentation/Changelog/2.0.0.rst | 65 +++++ Documentation/Index.rst | 4 + Documentation/Pageview.rst | 9 +- Documentation/Recordview.rst | 5 - Documentation/Tags.rst | 35 +++ Documentation/UpdateExistingRecords.rst | 5 + Resources/Private/Language/locallang_tca.xlf | 24 +- .../Command/UpdateDataCommandTest.php | 204 ++++++++++++++-- .../Provider/NewestPageviewsTest.php | 29 ++- .../Provider/PageviewsPerDayTest.php | 178 ++++++++++++-- .../PageviewsPerOperatingSystemTest.php | 151 +++++++++--- .../Provider/PageviewsPerPageTest.php | 188 +++++++++++--- .../Dashboard/Provider/RecordviewsTest.php | 83 +++---- .../Functional/Domain/Extractors/BotsTest.php | 183 ++++++++++++++ .../Domain/Recordview/FactoryTest.php | 22 +- Tests/Functional/Fixtures/Pages.xml | 50 ++++ .../Typo3FeaturesTest/PageWithRecords.xml | 1 - .../PageviewsWithMissingOperatingSystem.xml | 22 -- .../PageviewsWithOperatingSystem.xml | 22 -- .../WithCompatibleVersion.xml | 68 ++++++ .../WithMissingOperatingSystem.xml | 48 ++++ .../WithOperatingSystem.xml | 50 ++++ Tests/Functional/PageviewTest.php | 70 +++++- Tests/Functional/RecordviewTest.php | 27 +- Tests/Functional/Typo3FeaturesTest.php | 6 +- .../OperatingSystemTest.php} | 48 +++- Tests/Unit/Domain/Model/PageviewTest.php | 46 +--- Tests/Unit/Domain/Model/RecordRuleTest.php | 22 +- Tests/Unit/Domain/Model/RecordviewTest.php | 45 +--- Tests/Unit/Domain/Pageview/FactoryTest.php | 36 +-- Tests/Unit/Domain/Repository/PageviewTest.php | 231 ------------------ .../Unit/Domain/Repository/RecordviewTest.php | 80 ------ composer.json | 3 +- ext_tables.sql | 17 +- 62 files changed, 2574 insertions(+), 960 deletions(-) create mode 100644 Classes/Dashboard/Provider/Demand.php create mode 100644 Classes/Dashboard/Provider/Demand/Tag.php create mode 100644 Classes/Domain/Extractors/Bots.php create mode 100644 Classes/Domain/Extractors/Bots/CustomBotParser.php rename Classes/Domain/{Model/Extractor.php => Extractors/OperatingSystem.php} (68%) rename Classes/Domain/{Model/HasUserAgent.php => Extractors/PageviewExtractor.php} (73%) create mode 100644 Classes/Domain/Extractors/RecordviewExtractor.php create mode 100644 Classes/Domain/Extractors/Registry.php create mode 100644 Classes/Domain/Extractors/Tag.php create mode 100644 Classes/Domain/Repository/Tag.php create mode 100644 Configuration/Bots.yaml create mode 100644 Configuration/Services.php create mode 100644 Configuration/TCA/tx_tracking_tag.php create mode 100644 Documentation/Changelog/2.0.0.rst create mode 100644 Documentation/Tags.rst create mode 100644 Documentation/UpdateExistingRecords.rst create mode 100644 Tests/Functional/Domain/Extractors/BotsTest.php delete mode 100644 Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml delete mode 100644 Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml create mode 100644 Tests/Functional/Fixtures/UpdateDataCommandTest/WithCompatibleVersion.xml create mode 100644 Tests/Functional/Fixtures/UpdateDataCommandTest/WithMissingOperatingSystem.xml create mode 100644 Tests/Functional/Fixtures/UpdateDataCommandTest/WithOperatingSystem.xml rename Tests/Unit/Domain/{Model/ExtractorTest.php => Extractors/OperatingSystemTest.php} (67%) delete mode 100644 Tests/Unit/Domain/Repository/PageviewTest.php delete mode 100644 Tests/Unit/Domain/Repository/RecordviewTest.php diff --git a/Classes/Command/UpdateDataCommand.php b/Classes/Command/UpdateDataCommand.php index 4aa4f07..67494ab 100644 --- a/Classes/Command/UpdateDataCommand.php +++ b/Classes/Command/UpdateDataCommand.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace DanielSiepmann\Tracking\Command; use DanielSiepmann\Tracking\Domain\Repository\Pageview; +use DanielSiepmann\Tracking\Domain\Repository\Recordview; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; @@ -35,33 +36,58 @@ class UpdateDataCommand extends Command /** * @var Pageview */ - private $repository; + private $pageviews; - public function __construct(Pageview $repository) - { - $this->repository = $repository; + /** + * @var Recordview + */ + private $recordviews; + + public function __construct( + Pageview $pageviews, + Recordview $recordviews + ) { + $this->pageviews = $pageviews; + $this->recordviews = $recordviews; parent::__construct(); } protected function configure(): void { - $this->setDescription('Updates existing data.'); - $this->setHelp('In case some more data can be extracted of the existing data.'); + $this->setHelp('Converts legacy data to new format if necessary. Runs incrementel to work with large data sets.'); } protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); - $io->progressStart($this->repository->countAll()); - foreach ($this->repository->findAll() as $pageView) { - $this->repository->update($pageView); - $io->progressAdvance(); - } - - $io->progressFinish(); + $io->writeln('Updating: Pageviews'); + $this->update($this->pageviews, $io); + $io->writeln('Updating: Recordviews'); + $this->update($this->recordviews, $io); return 0; } + + /** + * @param Pageview|Recordview $repository + */ + private function update( + $repository, + SymfonyStyle $io + ): void { + $count = $repository->findLegacyCount(); + if ($count === 0) { + $io->writeln('No more data to update.'); + return; + } + + $io->progressStart($count); + foreach ($repository->findLegacy() as $data) { + $repository->update($data); + $io->progressAdvance(); + } + $io->progressFinish(); + } } diff --git a/Classes/Dashboard/Provider/Demand.php b/Classes/Dashboard/Provider/Demand.php new file mode 100644 index 0000000..c412f8f --- /dev/null +++ b/Classes/Dashboard/Provider/Demand.php @@ -0,0 +1,181 @@ + + * + * 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\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand\Tag; +use TYPO3\CMS\Core\Database\Connection; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; + +class Demand +{ + /** + * @var int + */ + private $days; + + /** + * @var int + */ + private $maxResults; + + /** + * @var int[] + */ + private $pagesToExclude; + + /** + * @var int[] + */ + private $languageLimitation; + + /** + * @var Tag[] + */ + private $tagConstraints; + + /** + * @param int[] $pagesToExclude + * @param int[] $languageLimitation + * @param Tag[] $tagConstraints + */ + public function __construct( + int $days = 31, + int $maxResults = 6, + array $pagesToExclude = [], + array $languageLimitation = [], + array $tagConstraints = [] + ) { + $this->days = $days; + $this->maxResults = $maxResults; + $this->pagesToExclude = array_map('intval', $pagesToExclude); + $this->languageLimitation = array_map('intval', $languageLimitation); + $this->tagConstraints = $tagConstraints; + } + + public function getDays(): int + { + return $this->days; + } + + public function getMaxResults(): int + { + return $this->maxResults; + } + + /** + * @return int[] + */ + public function getPagesToExclude(): array + { + return $this->pagesToExclude; + } + + /** + * @return int[] + */ + public function getLanguageLimitation(): array + { + return $this->languageLimitation; + } + + /** + * @return Tag[] + */ + public function getTagConstraints(): array + { + return $this->tagConstraints; + } + + public function addJoins( + QueryBuilder $queryBuilder, + string $tableName + ): void { + if ($this->getTagConstraints() !== []) { + $queryBuilder->leftJoin( + $tableName, + 'tx_tracking_tag', + 'tx_tracking_tag', + (string) $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq( + 'tx_tracking_tag.record_table_name', + $queryBuilder->createNamedParameter($tableName) + ), + $queryBuilder->expr()->eq( + 'tx_tracking_tag.record_uid', + $queryBuilder->quoteIdentifier($tableName . '.uid') + ) + ) + ); + } + } + + /** + * @return string[] + */ + public function getConstraints( + QueryBuilder $queryBuilder, + string $tableName + ): array { + $constraints = []; + + if ($this->getPagesToExclude() !== []) { + $constraints[] = (string) $queryBuilder->expr()->notIn( + $tableName . '.pid', + $queryBuilder->createNamedParameter( + $this->getPagesToExclude(), + Connection::PARAM_INT_ARRAY + ) + ); + } + + if ($this->getLanguageLimitation() !== []) { + $constraints[] = (string) $queryBuilder->expr()->in( + $tableName . '.sys_language_uid', + $queryBuilder->createNamedParameter( + $this->getLanguageLimitation(), + Connection::PARAM_INT_ARRAY + ) + ); + } + + foreach ($this->getTagConstraints() as $tagConstraint) { + $constraints[] = (string) $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq( + 'tx_tracking_tag.name', + $queryBuilder->createNamedParameter( + $tagConstraint->getName() + ) + ), + $queryBuilder->expr()->eq( + 'tx_tracking_tag.value', + $queryBuilder->createNamedParameter( + $tagConstraint->getValue() + ) + ) + ); + } + + return $constraints; + } +} diff --git a/Classes/Dashboard/Provider/Demand/Tag.php b/Classes/Dashboard/Provider/Demand/Tag.php new file mode 100644 index 0000000..e4ee471 --- /dev/null +++ b/Classes/Dashboard/Provider/Demand/Tag.php @@ -0,0 +1,64 @@ + + * + * 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\Dashboard\Provider\Demand; + +class Tag +{ + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $value; + + public function __construct( + string $name, + string $value + ) { + // TODO: Add Validate + $this->name = $name; + $this->value = $value; + } + + public static function createFromArray(array $parameters): self + { + return new self( + $parameters['name'], + $parameters['value'] + ); + } + + public function getName(): string + { + return $this->name; + } + + public function getValue(): string + { + return $this->value; + } +} diff --git a/Classes/Dashboard/Provider/NewestPageviews.php b/Classes/Dashboard/Provider/NewestPageviews.php index 0609db2..5f1b178 100644 --- a/Classes/Dashboard/Provider/NewestPageviews.php +++ b/Classes/Dashboard/Provider/NewestPageviews.php @@ -35,63 +35,35 @@ class NewestPageviews implements ListDataProviderInterface private $queryBuilder; /** - * @var int + * @var Demand */ - private $maxResults; - - /** - * @var array - */ - private $pagesToExclude; - - /** - * @var array - */ - private $languageLimitation; + private $demand; public function __construct( QueryBuilder $queryBuilder, - int $maxResults = 6, - array $pagesToExclude = [], - array $languageLimitation = [] + Demand $demand ) { $this->queryBuilder = $queryBuilder; - $this->maxResults = $maxResults; - $this->pagesToExclude = $pagesToExclude; - $this->languageLimitation = $languageLimitation; + $this->demand = $demand; } public function getItems(): array { $preparedItems = []; - $constraints = []; - if (count($this->pagesToExclude)) { - $constraints[] = $this->queryBuilder->expr()->notIn( - 'tx_tracking_pageview.pid', - $this->queryBuilder->createNamedParameter( - $this->pagesToExclude, - Connection::PARAM_INT_ARRAY - ) - ); - } + $constraints = $this->demand->getConstraints( + $this->queryBuilder, + 'tx_tracking_pageview' + ); - if (count($this->languageLimitation)) { - $constraints[] = $this->queryBuilder->expr()->in( - 'tx_tracking_pageview.sys_language_uid', - $this->queryBuilder->createNamedParameter( - $this->languageLimitation, - Connection::PARAM_INT_ARRAY - ) - ); - } + $this->demand->addJoins($this->queryBuilder, 'tx_tracking_pageview'); $this->queryBuilder ->select('url', 'user_agent') ->from('tx_tracking_pageview') ->orderBy('crdate', 'desc') ->addOrderBy('uid', 'desc') - ->setMaxResults($this->maxResults); + ->setMaxResults($this->demand->getMaxResults()); if ($constraints !== []) { $this->queryBuilder->where(...$constraints); diff --git a/Classes/Dashboard/Provider/PageviewsPerDay.php b/Classes/Dashboard/Provider/PageviewsPerDay.php index f44165b..c4c377b 100644 --- a/Classes/Dashboard/Provider/PageviewsPerDay.php +++ b/Classes/Dashboard/Provider/PageviewsPerDay.php @@ -43,38 +43,24 @@ class PageviewsPerDay implements ChartDataProviderInterface private $queryBuilder; /** - * @var int + * @var Demand */ - private $days; - - /** - * @var array - */ - private $pagesToExclude; + private $demand; /** * @var string */ private $dateFormat; - /** - * @var array - */ - private $languageLimitation; - public function __construct( LanguageService $languageService, QueryBuilder $queryBuilder, - int $days = 31, - array $pagesToExclude = [], - array $languageLimitation = [], + Demand $demand, string $dateFormat = 'Y-m-d' ) { $this->languageService = $languageService; $this->queryBuilder = $queryBuilder; - $this->days = $days; - $this->pagesToExclude = $pagesToExclude; - $this->languageLimitation = $languageLimitation; + $this->demand = $demand; $this->dateFormat = $dateFormat; } @@ -102,13 +88,13 @@ class PageviewsPerDay implements ChartDataProviderInterface $labels = []; $data = []; - for ($daysBefore = $this->days; $daysBefore >= 0; $daysBefore--) { + for ($daysBefore = $this->demand->getDays(); $daysBefore >= 0; $daysBefore--) { $label = date($this->dateFormat, (int) strtotime('-' . $daysBefore . ' day')); $labels[$label] = $label; $data[$label] = 0; } - $start = (int) strtotime('-' . $this->days . ' day 0:00:00'); + $start = (int) strtotime('-' . $this->demand->getDays() . ' day 0:00:00'); $end = (int) strtotime('tomorrow midnight'); @@ -125,32 +111,19 @@ class PageviewsPerDay implements ChartDataProviderInterface private function getPageviewsInPeriod(int $start, int $end): array { $constraints = [ - $this->queryBuilder->expr()->gte('crdate', $start), - $this->queryBuilder->expr()->lte('crdate', $end), + $this->queryBuilder->expr()->gte('tx_tracking_pageview.crdate', $start), + $this->queryBuilder->expr()->lte('tx_tracking_pageview.crdate', $end), ]; - if (count($this->pagesToExclude)) { - $constraints[] = $this->queryBuilder->expr()->notIn( - 'tx_tracking_pageview.pid', - $this->queryBuilder->createNamedParameter( - $this->pagesToExclude, - Connection::PARAM_INT_ARRAY - ) - ); - } + $constraints = array_merge($constraints, $this->demand->getConstraints( + $this->queryBuilder, + 'tx_tracking_pageview' + )); - if (count($this->languageLimitation)) { - $constraints[] = $this->queryBuilder->expr()->in( - 'tx_tracking_pageview.sys_language_uid', - $this->queryBuilder->createNamedParameter( - $this->languageLimitation, - Connection::PARAM_INT_ARRAY - ) - ); - } + $this->demand->addJoins($this->queryBuilder, 'tx_tracking_pageview'); $this->queryBuilder - ->addSelectLiteral('COUNT(*) as "count"') + ->addSelectLiteral('COUNT(tx_tracking_pageview.uid) as "count"') ->from('tx_tracking_pageview') ->where(...$constraints) ->groupBy('label') @@ -158,9 +131,9 @@ class PageviewsPerDay implements ChartDataProviderInterface ; if ($this->queryBuilder->getConnection()->getDatabasePlatform()->getName() === 'sqlite') { - $this->queryBuilder->addSelectLiteral('date(crdate, "unixepoch") as "label"'); + $this->queryBuilder->addSelectLiteral('date(tx_tracking_pageview.crdate, "unixepoch") as "label"'); } else { - $this->queryBuilder->addSelectLiteral('FROM_UNIXTIME(crdate, "%Y-%m-%d") as "label"'); + $this->queryBuilder->addSelectLiteral('FROM_UNIXTIME(tx_tracking_pageview.crdate, "%Y-%m-%d") as "label"'); } return $this->queryBuilder->execute()->fetchAll(); diff --git a/Classes/Dashboard/Provider/PageviewsPerOperatingSystem.php b/Classes/Dashboard/Provider/PageviewsPerOperatingSystem.php index 23da1ee..bfc61f2 100644 --- a/Classes/Dashboard/Provider/PageviewsPerOperatingSystem.php +++ b/Classes/Dashboard/Provider/PageviewsPerOperatingSystem.php @@ -36,30 +36,16 @@ class PageviewsPerOperatingSystem implements ChartDataProviderInterface private $queryBuilder; /** - * @var int + * @var Demand */ - private $days; - - /** - * @var int - */ - private $maxResults; - - /** - * @var array - */ - private $languageLimitation; + private $demand; public function __construct( QueryBuilder $queryBuilder, - int $days = 31, - int $maxResults = 6, - array $languageLimitation = [] + Demand $demand ) { $this->queryBuilder = $queryBuilder; - $this->days = $days; - $this->maxResults = $maxResults; - $this->languageLimitation = $languageLimitation; + $this->demand = $demand; } public function getChartData(): array @@ -85,33 +71,42 @@ class PageviewsPerOperatingSystem implements ChartDataProviderInterface $constraints = [ $this->queryBuilder->expr()->gte( 'tx_tracking_pageview.crdate', - strtotime('-' . $this->days . ' day 0:00:00') + strtotime('-' . $this->demand->getDays() . ' day 0:00:00') ), $this->queryBuilder->expr()->neq( - 'tx_tracking_pageview.operating_system', + 'operating_system', $this->queryBuilder->createNamedParameter('') ), ]; - if (count($this->languageLimitation)) { - $constraints[] = $this->queryBuilder->expr()->in( - 'tx_tracking_pageview.sys_language_uid', - $this->queryBuilder->createNamedParameter( - $this->languageLimitation, - Connection::PARAM_INT_ARRAY - ) - ); - } + $constraints = array_merge($constraints, $this->demand->getConstraints( + $this->queryBuilder, + 'tx_tracking_pageview' + )); + + $this->demand->addJoins($this->queryBuilder, 'tx_tracking_pageview'); $result = $this->queryBuilder - ->selectLiteral('count(operating_system) as total') - ->addSelect('operating_system') + ->addSelect('tag.value as operating_system') + ->addSelectLiteral( + 'count(' . $this->queryBuilder->quoteIdentifier('operating_system') . ') as total' + ) ->from('tx_tracking_pageview') + ->leftJoin( + 'tx_tracking_pageview', + 'tx_tracking_tag', + 'tag', + (string) $this->queryBuilder->expr()->andX( + $this->queryBuilder->expr()->eq('tx_tracking_pageview.uid', $this->queryBuilder->quoteIdentifier('tag.record_uid')), + $this->queryBuilder->expr()->eq('tag.name', $this->queryBuilder->createNamedParameter('os')), + $this->queryBuilder->expr()->eq('tag.record_table_name', $this->queryBuilder->createNamedParameter('tx_tracking_pageview')) + ) + ) ->where(...$constraints) - ->groupBy('tx_tracking_pageview.operating_system') + ->groupBy('operating_system') ->orderBy('total', 'desc') ->addOrderBy('operating_system', 'asc') - ->setMaxResults($this->maxResults) + ->setMaxResults($this->demand->getMaxResults()) ->execute() ->fetchAll(); diff --git a/Classes/Dashboard/Provider/PageviewsPerPage.php b/Classes/Dashboard/Provider/PageviewsPerPage.php index e07cf32..f1aaed5 100644 --- a/Classes/Dashboard/Provider/PageviewsPerPage.php +++ b/Classes/Dashboard/Provider/PageviewsPerPage.php @@ -45,39 +45,18 @@ class PageviewsPerPage implements ChartDataProviderInterface private $pageRepository; /** - * @var int + * @var Demand */ - private $days; - - /** - * @var int - */ - private $maxResults; - - /** - * @var array - */ - private $pagesToExclude; - - /** - * @var array - */ - private $languageLimitation; + private $demand; public function __construct( QueryBuilder $queryBuilder, PageRepository $pageRepository, - int $days = 31, - int $maxResults = 6, - array $pagesToExclude = [], - array $languageLimitation = [] + Demand $demand ) { $this->queryBuilder = $queryBuilder; $this->pageRepository = $pageRepository; - $this->days = $days; - $this->maxResults = $maxResults; - $this->pagesToExclude = $pagesToExclude; - $this->languageLimitation = $languageLimitation; + $this->demand = $demand; } public function getChartData(): array @@ -99,45 +78,33 @@ class PageviewsPerPage implements ChartDataProviderInterface { $labels = []; $data = []; - $constraints = [ - $this->queryBuilder->expr()->gte( + (string) $this->queryBuilder->expr()->gte( 'tx_tracking_pageview.crdate', - strtotime('-' . $this->days . ' day 0:00:00') + strtotime('-' . $this->demand->getDays() . ' day 0:00:00') ), ]; - if (count($this->pagesToExclude)) { - $constraints[] = $this->queryBuilder->expr()->notIn( - 'tx_tracking_pageview.pid', - $this->queryBuilder->createNamedParameter( - $this->pagesToExclude, - Connection::PARAM_INT_ARRAY - ) - ); - } - - if (count($this->languageLimitation)) { - $constraints[] = $this->queryBuilder->expr()->in( - 'tx_tracking_pageview.sys_language_uid', - $this->queryBuilder->createNamedParameter( - $this->languageLimitation, - Connection::PARAM_INT_ARRAY - ) - ); - } + $constraints = array_merge($constraints, $this->demand->getConstraints( + $this->queryBuilder, + 'tx_tracking_pageview' + )); + $this->demand->addJoins( + $this->queryBuilder, + 'tx_tracking_pageview' + ); $result = $this->queryBuilder ->selectLiteral( - $this->queryBuilder->expr()->count('pid', 'total'), - $this->queryBuilder->expr()->max('uid', 'latest') + $this->queryBuilder->expr()->count('tx_tracking_pageview.pid', 'total'), + $this->queryBuilder->expr()->max('tx_tracking_pageview.uid', 'latest') ) - ->addSelect('pid') + ->addSelect('tx_tracking_pageview.pid') ->from('tx_tracking_pageview') ->where(...$constraints) - ->groupBy('pid') + ->groupBy('tx_tracking_pageview.pid') ->orderBy('total', 'desc') ->addOrderBy('latest', 'desc') - ->setMaxResults($this->maxResults) + ->setMaxResults($this->demand->getMaxResults()) ->execute() ->fetchAll(); @@ -159,8 +126,8 @@ class PageviewsPerPage implements ChartDataProviderInterface private function getRecordTitle(int $uid): string { $record = BackendUtility::getRecord('pages', $uid); - if (count($this->languageLimitation) === 1 && $record !== null) { - $record = $this->pageRepository->getRecordOverlay('pages', $record, $this->languageLimitation[0]); + if (count($this->demand->getLanguageLimitation()) === 1 && $record !== null) { + $record = $this->pageRepository->getRecordOverlay('pages', $record, $this->demand->getLanguageLimitation()[0]); } if (is_array($record) === false) { diff --git a/Classes/Dashboard/Provider/Recordviews.php b/Classes/Dashboard/Provider/Recordviews.php index c0f7122..dca3eb4 100644 --- a/Classes/Dashboard/Provider/Recordviews.php +++ b/Classes/Dashboard/Provider/Recordviews.php @@ -49,24 +49,9 @@ class Recordviews implements ChartDataProviderInterface private $queryBuilder; /** - * @var int + * @var Demand */ - private $days; - - /** - * @var int - */ - private $maxResults; - - /** - * @var array - */ - private $pagesToExclude; - - /** - * @var array - */ - private $languageLimitation; + private $demand; /** * @var array @@ -81,19 +66,13 @@ class Recordviews implements ChartDataProviderInterface public function __construct( PageRepository $pageRepository, QueryBuilder $queryBuilder, - int $days = 31, - int $maxResults = 6, - array $pagesToExclude = [], - array $languageLimitation = [], + Demand $demand, array $recordTableLimitation = [], array $recordTypeLimitation = [] ) { $this->pageRepository = $pageRepository; $this->queryBuilder = $queryBuilder; - $this->days = $days; - $this->pagesToExclude = $pagesToExclude; - $this->languageLimitation = $languageLimitation; - $this->maxResults = $maxResults; + $this->demand = $demand; $this->recordTableLimitation = $recordTableLimitation; $this->recordTypeLimitation = $recordTypeLimitation; } @@ -152,30 +131,10 @@ class Recordviews implements ChartDataProviderInterface $constraints = [ $this->queryBuilder->expr()->gte( 'tx_tracking_recordview.crdate', - strtotime('-' . $this->days . ' day 0:00:00') + strtotime('-' . $this->demand->getDays() . ' day 0:00:00') ) ]; - if (count($this->pagesToExclude)) { - $constraints[] = $this->queryBuilder->expr()->notIn( - 'tx_tracking_recordview.pid', - $this->queryBuilder->createNamedParameter( - $this->pagesToExclude, - Connection::PARAM_INT_ARRAY - ) - ); - } - - 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', @@ -186,6 +145,15 @@ class Recordviews implements ChartDataProviderInterface ); } + $constraints = array_merge($constraints, $this->demand->getConstraints( + $this->queryBuilder, + 'tx_tracking_recordview' + )); + $this->demand->addJoins( + $this->queryBuilder, + 'tx_tracking_recordview' + ); + $result = $this->queryBuilder ->selectLiteral( $this->queryBuilder->expr()->count('record', 'total'), @@ -197,7 +165,7 @@ class Recordviews implements ChartDataProviderInterface ->groupBy('record', 'record_uid', 'record_table_name') ->orderBy('total', 'desc') ->addOrderBy('latest', 'desc') - ->setMaxResults($this->maxResults) + ->setMaxResults($this->demand->getMaxResults()) ->execute(); while ($row = $result->fetch()) { @@ -212,8 +180,8 @@ class Recordviews implements ChartDataProviderInterface $recordTypeField = $GLOBALS['TCA'][$table]['ctrl']['type'] ?? ''; $record = BackendUtility::getRecord($table, $uid); - if (count($this->languageLimitation) === 1 && $record !== null) { - $record = $this->pageRepository->getRecordOverlay($table, $record, $this->languageLimitation[0]); + if (count($this->demand->getLanguageLimitation()) === 1 && $record !== null) { + $record = $this->pageRepository->getRecordOverlay($table, $record, $this->demand->getLanguageLimitation()[0]); } if (is_array($record) === false) { diff --git a/Classes/Domain/Extractors/Bots.php b/Classes/Domain/Extractors/Bots.php new file mode 100644 index 0000000..73292a3 --- /dev/null +++ b/Classes/Domain/Extractors/Bots.php @@ -0,0 +1,88 @@ + + * + * 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\Extractors; + +use DanielSiepmann\Tracking\Domain\Extractors\Bots\CustomBotParser; +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; +use DeviceDetector\DeviceDetector; + +class Bots implements PageviewExtractor, RecordviewExtractor +{ + /** + * @var CustomBotParser + */ + private $customBotParser; + + public function __construct( + CustomBotParser $customBotParser + ) { + $this->customBotParser = $customBotParser; + } + + public function extractTagFromPageview(Pageview $pageview): array + { + return $this->getTagsForUserAgent($pageview->getUserAgent()); + } + + public function extractTagFromRecordview(Recordview $recordview): array + { + return $this->getTagsForUserAgent($recordview->getUserAgent()); + } + + /** + * @return Tag[] + */ + private function getTagsForUserAgent(string $userAgent): array + { + $botNameTag = new Tag('bot_name', $this->getBotName($userAgent)); + + if ($botNameTag->getValue() !== '') { + return [ + new Tag('bot', 'yes'), + $botNameTag, + ]; + } + return [new Tag('bot', 'no')]; + } + + private function getBotName(string $userAgent): string + { + $deviceDetector = new DeviceDetector(); + $deviceDetector->addBotParser($this->customBotParser); + $deviceDetector->setUserAgent($userAgent); + $deviceDetector->parse(); + + if ($deviceDetector->isBot() === false) { + return ''; + } + + $bot = $deviceDetector->getBot(); + if (is_array($bot) === false) { + return ''; + } + + return $bot['name'] ?? ''; + } +} diff --git a/Classes/Domain/Extractors/Bots/CustomBotParser.php b/Classes/Domain/Extractors/Bots/CustomBotParser.php new file mode 100644 index 0000000..de619e2 --- /dev/null +++ b/Classes/Domain/Extractors/Bots/CustomBotParser.php @@ -0,0 +1,56 @@ + + * + * 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\Extractors\Bots; + +use DeviceDetector\Parser\Bot; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +class CustomBotParser extends Bot +{ + protected $parserName = 'customBots'; + + /** + * @var string + */ + protected $dirName = ''; + + public function __construct() + { + parent::__construct(); + + $fixtureFile = GeneralUtility::getFileAbsFileName('EXT:tracking/Configuration/Bots.yaml'); + $this->fixtureFile = basename($fixtureFile); + $this->dirName = dirname($fixtureFile); + } + + protected function getRegexesDirectory(): string + { + return $this->dirName; + } + + public function parse(): ?array + { + return parent::parse(); + } +} diff --git a/Classes/Domain/Model/Extractor.php b/Classes/Domain/Extractors/OperatingSystem.php similarity index 68% rename from Classes/Domain/Model/Extractor.php rename to Classes/Domain/Extractors/OperatingSystem.php index 1bea76e..b01ca42 100644 --- a/Classes/Domain/Model/Extractor.php +++ b/Classes/Domain/Extractors/OperatingSystem.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * Copyright (C) 2020 Daniel Siepmann + * Copyright (C) 2021 Daniel Siepmann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -21,17 +21,25 @@ declare(strict_types=1); * 02110-1301, USA. */ -namespace DanielSiepmann\Tracking\Domain\Model; +namespace DanielSiepmann\Tracking\Domain\Extractors; -/** - * API to extract further info out of an model. - */ -class Extractor +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; + +class OperatingSystem implements PageviewExtractor, RecordviewExtractor { - public static function getOperatingSystem(HasUserAgent $model): string + public function extractTagFromPageview(Pageview $pageview): array { - $userAgent = $model->getUserAgent(); + return [new Tag('os', $this->getOperatingSystem($pageview->getUserAgent()))]; + } + public function extractTagFromRecordview(Recordview $recordview): array + { + return [new Tag('os', $this->getOperatingSystem($recordview->getUserAgent()))]; + } + + private function getOperatingSystem(string $userAgent): string + { if (mb_stripos($userAgent, 'Android') !== false) { return 'Android'; } @@ -57,6 +65,6 @@ class Extractor return 'iOS'; } - return ''; + return 'Unkown'; } } diff --git a/Classes/Domain/Model/HasUserAgent.php b/Classes/Domain/Extractors/PageviewExtractor.php similarity index 73% rename from Classes/Domain/Model/HasUserAgent.php rename to Classes/Domain/Extractors/PageviewExtractor.php index 6c3a686..d2afaca 100644 --- a/Classes/Domain/Model/HasUserAgent.php +++ b/Classes/Domain/Extractors/PageviewExtractor.php @@ -21,9 +21,17 @@ declare(strict_types=1); * 02110-1301, USA. */ -namespace DanielSiepmann\Tracking\Domain\Model; +namespace DanielSiepmann\Tracking\Domain\Extractors; -interface HasUserAgent +use DanielSiepmann\Tracking\Domain\Model\Pageview; + +/** + * API to extract further info out of an model. + */ +interface PageviewExtractor { - public function getUserAgent(): string; + /** + * @return Tag[] + */ + public function extractTagFromPageview(Pageview $pageview): array; } diff --git a/Classes/Domain/Extractors/RecordviewExtractor.php b/Classes/Domain/Extractors/RecordviewExtractor.php new file mode 100644 index 0000000..2855edd --- /dev/null +++ b/Classes/Domain/Extractors/RecordviewExtractor.php @@ -0,0 +1,37 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +namespace DanielSiepmann\Tracking\Domain\Extractors; + +use DanielSiepmann\Tracking\Domain\Model\Recordview; + +/** + * API to extract further info out of an model. + */ +interface RecordviewExtractor +{ + /** + * @return Tag[] + */ + public function extractTagFromRecordview(Recordview $recordview): array; +} diff --git a/Classes/Domain/Extractors/Registry.php b/Classes/Domain/Extractors/Registry.php new file mode 100644 index 0000000..df22d48 --- /dev/null +++ b/Classes/Domain/Extractors/Registry.php @@ -0,0 +1,74 @@ + + * + * 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\Extractors; + +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; + +class Registry +{ + /** + * @var PageviewExtractor[] + */ + protected $pageviewExtractors = []; + + /** + * @var RecordviewExtractor[] + */ + protected $recordviewExtractors = []; + + public function addPageviewExtractor(PageviewExtractor $extractor): void + { + $this->pageviewExtractors[] = $extractor; + } + + public function addRecordviewExtractor(RecordviewExtractor $extractor): void + { + $this->recordviewExtractors[] = $extractor; + } + + /** + * @return Tag[] + */ + public function getTagsForPageview(Pageview $pageview): array + { + $tags = []; + foreach ($this->pageviewExtractors as $extractor) { + $tags = array_merge($tags, $extractor->extractTagFromPageview($pageview)); + } + return $tags; + } + + /** + * @return Tag[] + */ + public function getTagsForRecordview(Recordview $recordview): array + { + $tags = []; + foreach ($this->recordviewExtractors as $extractor) { + $tags = array_merge($tags, $extractor->extractTagFromRecordview($recordview)); + } + return $tags; + } +} diff --git a/Classes/Domain/Extractors/Tag.php b/Classes/Domain/Extractors/Tag.php new file mode 100644 index 0000000..b869355 --- /dev/null +++ b/Classes/Domain/Extractors/Tag.php @@ -0,0 +1,57 @@ + + * + * 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\Extractors; + +class Tag +{ + /** + * E.g. "os" or "bot", some unique identifier. + * + * @var string + */ + protected $name = ''; + + /** + * @var string + */ + protected $value = ''; + + public function __construct( + string $name, + string $value + ) { + $this->name = $name; + $this->value = $value; + } + + public function getName(): string + { + return $this->name; + } + + public function getValue(): string + { + return $this->value; + } +} diff --git a/Classes/Domain/Model/Pageview.php b/Classes/Domain/Model/Pageview.php index a09fca8..b0f723c 100644 --- a/Classes/Domain/Model/Pageview.php +++ b/Classes/Domain/Model/Pageview.php @@ -25,7 +25,7 @@ namespace DanielSiepmann\Tracking\Domain\Model; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -class Pageview implements HasUserAgent +class Pageview { /** * @var int @@ -114,9 +114,4 @@ class Pageview implements HasUserAgent { return $this->userAgent; } - - public function getOperatingSystem(): string - { - return Extractor::getOperatingSystem($this); - } } diff --git a/Classes/Domain/Model/Recordview.php b/Classes/Domain/Model/Recordview.php index 46407fd..039b0b8 100644 --- a/Classes/Domain/Model/Recordview.php +++ b/Classes/Domain/Model/Recordview.php @@ -25,8 +25,13 @@ namespace DanielSiepmann\Tracking\Domain\Model; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -class Recordview implements HasUserAgent +class Recordview { + /** + * @var int + */ + private $uid = 0; + /** * @var int */ @@ -69,8 +74,10 @@ class Recordview implements HasUserAgent string $url, string $userAgent, int $recordUid, - string $tableName + string $tableName, + int $uid = 0 ) { + $this->uid = $uid; $this->pageUid = $pageUid; $this->language = $language; $this->crdate = $crdate; @@ -80,6 +87,11 @@ class Recordview implements HasUserAgent $this->tableName = $tableName; } + public function getUid(): int + { + return $this->uid; + } + public function getPageUid(): int { return $this->pageUid; @@ -114,9 +126,4 @@ class Recordview implements HasUserAgent { return $this->tableName; } - - public function getOperatingSystem(): string - { - return Extractor::getOperatingSystem($this); - } } diff --git a/Classes/Domain/Recordview/Factory.php b/Classes/Domain/Recordview/Factory.php index f8d9cfe..28a0354 100644 --- a/Classes/Domain/Recordview/Factory.php +++ b/Classes/Domain/Recordview/Factory.php @@ -30,6 +30,7 @@ use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use TYPO3\CMS\Core\Routing\PageArguments; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; +use TYPO3\CMS\Core\Site\SiteFinder; class Factory { @@ -38,9 +39,16 @@ class Factory */ private $expressionFactory; + /** + * @var SiteFinder + */ + private $siteFinder; + public function __construct( + SiteFinder $siteFinder, ExpressionFactory $expressionFactory ) { + $this->siteFinder = $siteFinder; $this->expressionFactory = $expressionFactory; } @@ -75,6 +83,20 @@ class Factory ); } + public function fromDbRow(array $dbRow): Recordview + { + return new Recordview( + $dbRow['pid'], + $this->siteFinder->getSiteByPageId($dbRow['pid'])->getLanguageById($dbRow['sys_language_uid']), + new \DateTimeImmutable('@' . $dbRow['crdate']), + $dbRow['url'], + $dbRow['user_agent'], + $dbRow['record_uid'], + $dbRow['record_table_name'], + $dbRow['uid'] + ); + } + private static function getLanguage(ServerRequestInterface $request): SiteLanguage { $language = $request->getAttribute('language'); diff --git a/Classes/Domain/Repository/Pageview.php b/Classes/Domain/Repository/Pageview.php index 856c568..d4ad93b 100644 --- a/Classes/Domain/Repository/Pageview.php +++ b/Classes/Domain/Repository/Pageview.php @@ -25,6 +25,7 @@ namespace DanielSiepmann\Tracking\Domain\Repository; use DanielSiepmann\Tracking\Domain\Model\Pageview as Model; use DanielSiepmann\Tracking\Domain\Pageview\Factory; +use DanielSiepmann\Tracking\Extension; use TYPO3\CMS\Core\Database\Connection; class Pageview @@ -39,33 +40,50 @@ class Pageview */ private $factory; + /** + * @var Tag + */ + private $tagRepository; + public function __construct( Connection $connection, - Factory $factory + Factory $factory, + Tag $tagRepository ) { $this->connection = $connection; $this->factory = $factory; + $this->tagRepository = $tagRepository; } - public function countAll(): int - { - $result = $this->connection->createQueryBuilder() - ->count('uid') - ->from('tx_tracking_pageview') - ->execute() - ->fetchColumn(); - - if (is_numeric($result)) { - return (int) $result; - } - - return 0; - } - - public function findAll(): \Generator + public function findLegacyCount(): int { $queryBuilder = $this->connection->createQueryBuilder(); - $pageViews = $queryBuilder->select('*')->from('tx_tracking_pageview')->execute(); + $queryBuilder->count('*'); + $queryBuilder->from('tx_tracking_pageview'); + $queryBuilder->where($queryBuilder->expr()->neq('compatible_version', $queryBuilder->createNamedParameter(Extension::getCompatibleVersionNow()))); + $queryBuilder->setMaxResults(Extension::getMaximumRowsForUpdate()); + + $pageViews = $queryBuilder->execute()->fetchColumn(); + if (is_numeric($pageViews) === false) { + return 0; + } + + if ($pageViews > Extension::getMaximumRowsForUpdate()) { + return Extension::getMaximumRowsForUpdate(); + } + return (int) $pageViews; + } + + public function findLegacy(): \Generator + { + $queryBuilder = $this->connection->createQueryBuilder(); + $queryBuilder->select('*'); + $queryBuilder->from('tx_tracking_pageview'); + $queryBuilder->where($queryBuilder->expr()->neq('compatible_version', $queryBuilder->createNamedParameter(Extension::getCompatibleVersionNow()))); + $test = Extension::getCompatibleVersionNow(); + $queryBuilder->setMaxResults(Extension::getMaximumRowsForUpdate()); + + $pageViews = $queryBuilder->execute(); while ($pageView = $pageViews->fetch()) { if (is_array($pageView) === false) { @@ -87,6 +105,8 @@ class Pageview $this->getFieldsFromModel($pageview), ['uid' => $pageview->getUid()] ); + + $this->tagRepository->updateForPageview($pageview); } public function add(Model $pageview): void @@ -95,6 +115,11 @@ class Pageview 'tx_tracking_pageview', $this->getFieldsFromModel($pageview) ); + + $this->tagRepository->addForPageview( + $pageview, + (int) $this->connection->lastInsertId('tx_tracking_pageview') + ); } private function getFieldsFromModel(Model $pageview): array @@ -107,7 +132,7 @@ class Pageview 'sys_language_uid' => $pageview->getLanguage()->getLanguageId(), 'url' => $pageview->getUrl(), 'user_agent' => $pageview->getUserAgent(), - 'operating_system' => $pageview->getOperatingSystem(), + 'compatible_version' => Extension::getCompatibleVersionNow(), ]; } } diff --git a/Classes/Domain/Repository/Recordview.php b/Classes/Domain/Repository/Recordview.php index 15edb4f..e669a1d 100644 --- a/Classes/Domain/Repository/Recordview.php +++ b/Classes/Domain/Repository/Recordview.php @@ -24,8 +24,13 @@ declare(strict_types=1); namespace DanielSiepmann\Tracking\Domain\Repository; use DanielSiepmann\Tracking\Domain\Model\Recordview as Model; +use DanielSiepmann\Tracking\Domain\Recordview\Factory; +use DanielSiepmann\Tracking\Extension; use TYPO3\CMS\Core\Database\Connection; +// TODO: Move common code to API class. +// Call API Class with table name + class Recordview { /** @@ -33,10 +38,77 @@ class Recordview */ private $connection; + /** + * @var Factory + */ + private $factory; + + /** + * @var Tag + */ + private $tagRepository; + public function __construct( - Connection $connection + Connection $connection, + Factory $factory, + Tag $tagRepository ) { $this->connection = $connection; + $this->factory = $factory; + $this->tagRepository = $tagRepository; + } + + public function findLegacyCount(): int + { + $queryBuilder = $this->connection->createQueryBuilder(); + $queryBuilder->count('*'); + $queryBuilder->from('tx_tracking_recordview'); + $queryBuilder->where($queryBuilder->expr()->neq('compatible_version', $queryBuilder->createNamedParameter(Extension::getCompatibleVersionNow()))); + $queryBuilder->setMaxResults(Extension::getMaximumRowsForUpdate()); + + $recordviews = $queryBuilder->execute()->fetchColumn(); + if (is_numeric($recordviews) === false) { + return 0; + } + + if ($recordviews > Extension::getMaximumRowsForUpdate()) { + return Extension::getMaximumRowsForUpdate(); + } + return (int) $recordviews; + } + + public function findLegacy(): \Generator + { + $queryBuilder = $this->connection->createQueryBuilder(); + $queryBuilder->select('*'); + $queryBuilder->from('tx_tracking_recordview'); + $queryBuilder->where($queryBuilder->expr()->neq('compatible_version', $queryBuilder->createNamedParameter(Extension::getCompatibleVersionNow()))); + $queryBuilder->setMaxResults(Extension::getMaximumRowsForUpdate()); + + $recordviews = $queryBuilder->execute(); + + while ($pageView = $recordviews->fetch()) { + if (is_array($pageView) === false) { + continue; + } + + yield $this->factory->fromDbRow($pageView); + } + } + + public function update(Model $model): void + { + if ($model->getUid() === 0) { + throw new \InvalidArgumentException('Can not update recordview if uid is 0.', 1585770573); + } + + $this->connection->update( + 'tx_tracking_recordview', + $this->getFieldsFromModel($model), + ['uid' => $model->getUid()] + ); + + $this->tagRepository->updateForRecordview($model); } public function add(Model $recordview): void @@ -45,6 +117,11 @@ class Recordview 'tx_tracking_recordview', $this->getFieldsFromModel($recordview) ); + + $this->tagRepository->addForRecordview( + $recordview, + (int) $this->connection->lastInsertId('tx_tracking_recordview') + ); } private function getFieldsFromModel(Model $recordview): array @@ -56,10 +133,10 @@ class Recordview 'sys_language_uid' => $recordview->getLanguage()->getLanguageId(), 'url' => $recordview->getUrl(), 'user_agent' => $recordview->getUserAgent(), - 'operating_system' => $recordview->getOperatingSystem(), 'record_uid' => $recordview->getRecordUid(), 'record_table_name' => $recordview->getTableName(), 'record' => $recordview->getTableName() . '_' . $recordview->getRecordUid(), + 'compatible_version' => Extension::getCompatibleVersionNow(), ]; } } diff --git a/Classes/Domain/Repository/Tag.php b/Classes/Domain/Repository/Tag.php new file mode 100644 index 0000000..8399f51 --- /dev/null +++ b/Classes/Domain/Repository/Tag.php @@ -0,0 +1,119 @@ + + * + * 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\Repository; + +use DanielSiepmann\Tracking\Domain\Extractors\Registry; +use DanielSiepmann\Tracking\Domain\Extractors\Tag as Model; +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; +use DanielSiepmann\Tracking\Extension; +use TYPO3\CMS\Core\Database\Connection; + +class Tag +{ + /** + * @var Connection + */ + private $connection; + + /** + * @var Registry + */ + private $extractorRegistry; + + public function __construct( + Connection $connection, + Registry $extractorRegistry + ) { + $this->connection = $connection; + $this->extractorRegistry = $extractorRegistry; + } + + public function addForPageview( + Pageview $pageview, + int $recordUid + ): void { + foreach ($this->extractorRegistry->getTagsForPageview($pageview) as $tag) { + $this->connection->insert( + 'tx_tracking_tag', + [ + 'pid' => $pageview->getPageUid(), + 'crdate' => $pageview->getCrdate()->format('U'), + 'tstamp' => $pageview->getCrdate()->format('U'), + 'record_uid' => $recordUid, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => $tag->getName(), + 'value' => $tag->getValue(), + ] + ); + } + } + + public function updateForPageview( + Pageview $pageview + ): void { + $this->connection->delete( + 'tx_tracking_tag', + [ + 'record_uid' => $pageview->getUid(), + 'record_table_name' => 'tx_tracking_pageview', + ] + ); + $this->addForPageview($pageview, $pageview->getUid()); + } + + public function addForRecordview( + Recordview $recordview, + int $recordUid + ): void { + foreach ($this->extractorRegistry->getTagsForRecordview($recordview) as $tag) { + $this->connection->insert( + 'tx_tracking_tag', + [ + 'pid' => $recordview->getPageUid(), + 'crdate' => $recordview->getCrdate()->format('U'), + 'tstamp' => $recordview->getCrdate()->format('U'), + 'record_uid' => $recordUid, + 'record_table_name' => 'tx_tracking_recordview', + 'name' => $tag->getName(), + 'value' => $tag->getValue(), + 'compatible_version' => Extension::getCompatibleVersionNow(), + ] + ); + } + } + + public function updateForRecordview( + Recordview $recordview + ): void { + $this->connection->delete( + 'tx_tracking_tag', + [ + 'record_uid' => $recordview->getUid(), + 'record_table_name' => 'tx_tracking_recordview', + ] + ); + $this->addForRecordview($recordview, $recordview->getUid()); + } +} diff --git a/Classes/Extension.php b/Classes/Extension.php index 4b005d2..d297a62 100644 --- a/Classes/Extension.php +++ b/Classes/Extension.php @@ -28,4 +28,15 @@ final class Extension public const EXT_KEY = 'tracking'; public const LANGUAGE_PATH = 'LLL:EXT:' . self::EXT_KEY . '/Resources/Private/Language/locallang.xlf'; + + public static function getCompatibleVersionNow(): string + { + return 'v2.0.0'; + } + + public static function getMaximumRowsForUpdate(): int + { + // TODO: Make configurable + return 3500; + } } diff --git a/Configuration/Bots.yaml b/Configuration/Bots.yaml new file mode 100644 index 0000000..77d9d2f --- /dev/null +++ b/Configuration/Bots.yaml @@ -0,0 +1,18 @@ +- regex: 'nettle' + name: 'Nettle' +- regex: 'crusty' + name: 'Crusty' +- regex: 'Faraday' + name: 'Faraday' +- regex: 'newspaper' + name: 'Newspaper' +- regex: 'uni-passau' + name: 'Uni Passau' +- regex: 'Upflow' + name: 'Upflow' +- regex: 'MauiBot' + name: 'Maui Bot' +- regex: 'Java' + name: 'Java' +- regex: 'python-requests' + name: 'Python Requests' diff --git a/Configuration/Services.php b/Configuration/Services.php new file mode 100644 index 0000000..4f2ce42 --- /dev/null +++ b/Configuration/Services.php @@ -0,0 +1,40 @@ +registerForAutoconfiguration(PageviewExtractor::class)->addTag('tracking.extractor.pageview'); + $containerBuilder->registerForAutoconfiguration(RecordviewExtractor::class)->addTag('tracking.extractor.recordview'); + $containerBuilder->addCompilerPass(new class() implements CompilerPassInterface { + public function process(ContainerBuilder $containerBuilder): void + { + $registry = $containerBuilder->findDefinition(Registry::class); + foreach ($containerBuilder->findTaggedServiceIds('tracking.extractor.pageview') as $id => $tags) { + $definition = $containerBuilder->findDefinition($id); + if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + continue; + } + + $registry->addMethodCall('addPageviewExtractor', [$definition]); + } + foreach ($containerBuilder->findTaggedServiceIds('tracking.extractor.recordview') as $id => $tags) { + $definition = $containerBuilder->findDefinition($id); + if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + continue; + } + + $registry->addMethodCall('addRecordviewExtractor', [$definition]); + } + } + }); +}; + diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index df8bb13..e3a915f 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -43,6 +43,14 @@ services: arguments: - 'tx_tracking_recordview' + dbconnection.tx_tracking_tag: + class: 'TYPO3\CMS\Core\Database\Connection' + factory: + - '@TYPO3\CMS\Core\Database\ConnectionPool' + - 'getConnectionForTable' + arguments: + - 'tx_tracking_tag' + DanielSiepmann\Tracking\Domain\Repository\Pageview: public: true arguments: @@ -53,18 +61,17 @@ services: arguments: - '@dbconnection.tx_tracking_recordview' + DanielSiepmann\Tracking\Domain\Repository\Tag: + public: true + arguments: + - '@dbconnection.tx_tracking_tag' + DanielSiepmann\Tracking\Middleware\Pageview: public: true arguments: $rule: > not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) - and traverse(request.getHeader("User-Agent"), '0') - and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") - and not (request.getHeader("User-Agent")[0] matches "/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/") - and not (request.getHeader("User-Agent")[0] matches "/UptimeRobot|Pingdom/") DanielSiepmann\Tracking\Middleware\Recordview: public: true @@ -75,3 +82,4 @@ services: tags: - name: 'console.command' command: 'tracking:updatedata' + description: 'Updates existing data.' diff --git a/Configuration/TCA/tx_tracking_pageview.php b/Configuration/TCA/tx_tracking_pageview.php index 89c39ae..8c61f09 100644 --- a/Configuration/TCA/tx_tracking_pageview.php +++ b/Configuration/TCA/tx_tracking_pageview.php @@ -17,7 +17,7 @@ return [ ], 'types' => [ '0' => [ - 'showitem' => 'sys_language_uid, pid, url, user_agent, operating_system, type, crdate', + 'showitem' => 'sys_language_uid, pid, url, user_agent, tags, type, crdate', ], ], 'columns' => [ @@ -56,10 +56,13 @@ return [ 'readOnly' => true, ], ], - 'operating_system' => [ - 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.pageview.operating_system', + 'tags' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.pageview.tags', 'config' => [ - 'type' => 'input', + 'type' => 'inline', + 'foreign_table' => 'tx_tracking_tag', + 'foreign_field' => 'record_uid', + 'foreign_table_field' => 'record_table_name', 'readOnly' => true, ], ], diff --git a/Configuration/TCA/tx_tracking_recordview.php b/Configuration/TCA/tx_tracking_recordview.php index 98085c0..fffe3cf 100644 --- a/Configuration/TCA/tx_tracking_recordview.php +++ b/Configuration/TCA/tx_tracking_recordview.php @@ -17,7 +17,7 @@ return [ ], 'types' => [ '0' => [ - 'showitem' => 'sys_language_uid, pid, record, url, user_agent, operating_system, crdate', + 'showitem' => 'sys_language_uid, pid, record, url, user_agent, tags, crdate', ], ], 'columns' => [ @@ -56,13 +56,6 @@ return [ 'readOnly' => true, ], ], - 'operating_system' => [ - 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.recordview.operating_system', - 'config' => [ - 'type' => 'input', - 'readOnly' => true, - ], - ], 'url' => [ 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.recordview.url', 'config' => [ @@ -82,5 +75,15 @@ return [ 'size' => 1, ], ], + 'tags' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.recordview.tags', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_tracking_tag', + 'foreign_field' => 'record_uid', + 'foreign_table_field' => 'record_table_name', + 'readOnly' => true, + ], + ], ], ]; diff --git a/Configuration/TCA/tx_tracking_tag.php b/Configuration/TCA/tx_tracking_tag.php new file mode 100644 index 0000000..88795e8 --- /dev/null +++ b/Configuration/TCA/tx_tracking_tag.php @@ -0,0 +1,67 @@ + [ + 'label' => 'name', + 'label_alt' => 'value', + 'label_alt_force' => true, + 'default_sortby' => 'crdate DESC', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'hideTable' => true, + 'title' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag', + ], + 'types' => [ + '0' => [ + 'showitem' => 'pid, record_uid, record_table_name, name, value', + ], + ], + 'columns' => [ + 'pid' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.pid', + 'config' => [ + // TYPO3 v10 does no longer allow to resolve PID relations, e.g. via select or group + // This will break internal PID handling. + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'record_uid' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.record_uid', + 'config' => [ + 'type' => 'input', + 'eval' => 'int', + 'readOnly' => true, + ], + ], + 'record_table_name' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.record_table_name', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'crdate' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.crdate', + 'config' => [ + 'type' => 'input', + 'eval' => 'datetime', + ], + ], + 'name' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.name', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'value' => [ + 'label' => 'LLL:EXT:tracking/Resources/Private/Language/locallang_tca.xlf:table.tag.value', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + ], +]; diff --git a/Documentation/Changelog/2.0.0.rst b/Documentation/Changelog/2.0.0.rst new file mode 100644 index 0000000..18ce3c3 --- /dev/null +++ b/Documentation/Changelog/2.0.0.rst @@ -0,0 +1,65 @@ +2.0.0 +===== + +Breaking +-------- + +* No longer has ``operating_system`` database column. + +* No longer ships default rule to not track requests from bots. + Does track them as bots now. + + How to update: + + Remove custom adjustments from :file:`Services.yaml` regarding bot detection. + Instead extend built in bot extraction and adjust custom widgets to exclude those + bots. + + Execute the provided command (scheduler task) to update existing data. + Bots and operating system will be extracted from stored user agent. + + See: :ref:`tags`. + +* Existing widgets will no longer work with custom configuration. + Configuration needs to be adjusted. + + .. todo:: document how to migrate + +* Widgets will not work with old data. + How to migrate data: + + Execute the provided scheduler task. + It will incrementally update pageviews and recordviews. + 3500 records of each will be updated per each run. + Roughly executing every 10 minutes seems to be a good idea. + +Features +-------- + +* Added support for tags + + Tags can now be added to :ref:`pageview` and :ref:`recordview`. + The extension ships with some out of the box, but further can be added, see + :ref:`tags`. + + Resolves: :issue:`46`. + + Sponsored by: https://www.werkraum-media.de/ + +* Uses ``matomo/device-detector`` library to detect bots. + Some known bots are added on top. + +Fixes +----- + +Nothing + +Tasks +----- + +Nothing + +Deprecation +----------- + +Nothing diff --git a/Documentation/Index.rst b/Documentation/Index.rst index 80225d0..3236356 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -41,6 +41,8 @@ The extension allows to track :ref:`pageview`, as well as views to specific TYPO3 records via :ref:`recordview`, e.g. records from EXT:news or EXT:tt_address. +Each of them can be extended with arbitrary tags extracted from request. + Missing features ---------------- @@ -90,4 +92,6 @@ in order to extract further information from them with future updates. Installation Pageview Recordview + Tags + UpdateExistingRecords Changelog diff --git a/Documentation/Pageview.rst b/Documentation/Pageview.rst index c6393ca..431167c 100644 --- a/Documentation/Pageview.rst +++ b/Documentation/Pageview.rst @@ -43,12 +43,6 @@ Let us examine an concrete example:: $rule: > not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) - and traverse(request.getHeader("User-Agent"), '0') - and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") - and not (request.getHeader("User-Agent")[0] matches "/^Codeception Testing/") - and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") - 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/") The first paragraph will not be explained, check out :ref:`t3coreapi:configure-dependency-injection-in-extensions` instead. @@ -71,8 +65,7 @@ Check `PSR-7: HTTP message interfaces 0 and not (context.getAspect("backend.user").isLoggedIn()) and not (context.getAspect("frontend.preview").isPreview()) - and traverse(request.getHeader("User-Agent"), '0') - and not (request.getHeader("User-Agent")[0] matches "/^TYPO3|TYPO3 linkvalidator/") - and not (request.getHeader("User-Agent")[0] matches "/Wget|curl|Go-http-client/") - and not (request.getHeader("User-Agent")[0] matches "/bot|spider|Slurp|Sogou|NextCloud-News|Feedly|XING FeedReader|SEOkicks|Seekport Crawler|ia_archiver|TrendsmapResolver|Nuzzel/") - and not (request.getHeader("User-Agent")[0] matches "/mattermost|Slackbot|WhatsApp/") recordUid: 'traverse(request.getQueryParams(), "tx_news_pi1", "news")' tableName: 'tx_news_domain_model_news' diff --git a/Documentation/Tags.rst b/Documentation/Tags.rst new file mode 100644 index 0000000..8d07667 --- /dev/null +++ b/Documentation/Tags.rst @@ -0,0 +1,35 @@ +.. _tags: + +Tags +===== + +Tags are attached to all tracking information like :ref:`pageview` and :ref:`recordview`. +An example for a single record would be: ``bot:"yes",bot_name:"Slack",os:"Unkown"``. + +Tags are extracted whenever a new record is saved, also during :ref:`updateExistingRecords`. + +The extension provides some extractors to attach tags out of the box. +Further can be provided by foreign extensions or sites. +Each extractor has to implement either ``DanielSiepmann\Tracking\Domain\Extractors\PageviewExtractor`` and \ or ``DanielSiepmann\Tracking\Domain\Extractors\RecordviewExtractor`` interface. + +This allows to add arbitrary data as tags to each tracking record. +Those can then be used to generate reports or build widgets. + +Existing extractors +------------------- + +The following are provided out of the box. +One can replace them using :file:`Services.yaml`. + +Operating System +^^^^^^^^^^^^^^^^ + +Contains old logic to detect operating system of requests. +The operating system is added as ``os`` tag, e.g.: ``os:"Macintosh"``. + +Bots +^^^^ + +Contains old logic to detect bots of requests. +The bot is added either as ``bot:"no"``. +If a bot is detected it is added as ``bot:"yes"`` combined with its name ``bot_name:"Slack"``. diff --git a/Documentation/UpdateExistingRecords.rst b/Documentation/UpdateExistingRecords.rst new file mode 100644 index 0000000..bfcf62c --- /dev/null +++ b/Documentation/UpdateExistingRecords.rst @@ -0,0 +1,5 @@ +.. highlight:: php +.. _updateExistingRecords: + +Update existing records +======================= diff --git a/Resources/Private/Language/locallang_tca.xlf b/Resources/Private/Language/locallang_tca.xlf index 4043044..c522c7f 100644 --- a/Resources/Private/Language/locallang_tca.xlf +++ b/Resources/Private/Language/locallang_tca.xlf @@ -27,8 +27,8 @@ User agent - - Operating System + + Tags @@ -55,8 +55,24 @@ User agent - - Operating System + + Tags + + + + PID + + + Foreign Record UID + + + Foreign Record Table Name + + + Name + + + Value diff --git a/Tests/Functional/Command/UpdateDataCommandTest.php b/Tests/Functional/Command/UpdateDataCommandTest.php index ac85d23..cc452d6 100644 --- a/Tests/Functional/Command/UpdateDataCommandTest.php +++ b/Tests/Functional/Command/UpdateDataCommandTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,16 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Command; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Command; + use DanielSiepmann\Tracking\Command\UpdateDataCommand; +use DanielSiepmann\Tracking\Extension; 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 + * @covers \DanielSiepmann\Tracking\Command\UpdateDataCommand */ class UpdateDataCommandTest extends TestCase { @@ -44,18 +47,112 @@ class UpdateDataCommandTest extends TestCase */ public function updatesAllEntriesWithMissingOperatingSystem(): void { - $this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml'); + $this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/WithMissingOperatingSystem.xml'); $subject = GeneralUtility::makeInstance(UpdateDataCommand::class); $tester = new CommandTester($subject); $tester->execute([], ['capture_stderr_separately' => true]); - static::assertSame(0, $tester->getStatusCode()); + self::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']); + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(8, $records); + self::assertSame([ + 'uid'=> '1', + 'pid'=> '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id'=> '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[0])); + self::assertSame([ + 'uid'=> '2', + 'pid'=> '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id'=> '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'Linux', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[1])); + self::assertSame([ + 'uid'=> '3', + 'pid'=> '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id'=> '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[2])); + self::assertSame([ + 'uid'=> '4', + 'pid'=> '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id'=> '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'Android', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[3])); + self::assertSame([ + 'uid'=> '5', + 'pid'=> '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id'=> '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_recordview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[4])); + self::assertSame([ + 'uid'=> '6', + 'pid'=> '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id'=> '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_recordview', + 'name' => 'os', + 'value' => 'Linux', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[5])); + self::assertSame([ + 'uid'=> '7', + 'pid'=> '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id'=> '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_recordview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[6])); + self::assertSame([ + 'uid'=> '8', + 'pid'=> '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id'=> '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_recordview', + 'name' => 'os', + 'value' => 'Android', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[7])); } /** @@ -63,18 +160,64 @@ class UpdateDataCommandTest extends TestCase */ public function doesNotChangeExistingOperatingSystem(): void { - $this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml'); + $this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/WithOperatingSystem.xml'); $subject = GeneralUtility::makeInstance(UpdateDataCommand::class); $tester = new CommandTester($subject); $tester->execute([], ['capture_stderr_separately' => true]); - static::assertSame(0, $tester->getStatusCode()); + self::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']); + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(4, $records); + self::assertSame([ + 'uid' => '3', + 'pid' => '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id' => '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[0])); + self::assertSame([ + 'uid' => '4', + 'pid' => '1', + 'tstamp'=> '1630649915', + 'crdate'=> '1630649915', + 'cruser_id' => '0', + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'Linux', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[1])); + self::assertSame([ + 'uid' => '5', + 'pid' => '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id' => '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[2])); + self::assertSame([ + 'uid' => '6', + 'pid' => '1', + 'tstamp'=> '1630649916', + 'crdate'=> '1630649916', + 'cruser_id' => '0', + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'Android', + 'compatible_version' => Extension::getCompatibleVersionNow(), + ], array_map('strval', $records[3])); } /** @@ -88,9 +231,38 @@ class UpdateDataCommandTest extends TestCase $tester = new CommandTester($subject); $tester->execute([], ['capture_stderr_separately' => true]); - static::assertSame(0, $tester->getStatusCode()); + self::assertSame(0, $tester->getStatusCode()); $records = $this->getAllRecords('tx_tracking_pageview'); - static::assertCount(0, $records); + self::assertCount(0, $records); + + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(0, $records); + } + + /** + * @test + */ + public function doesNothingIfAllRecordsAreCompatible(): void + { + $this->importDataSet('EXT:tracking/Tests/Functional/Fixtures/UpdateDataCommandTest/WithCompatibleVersion.xml'); + + $subject = GeneralUtility::makeInstance(UpdateDataCommand::class); + $tester = new CommandTester($subject); + $tester->execute([], ['capture_stderr_separately' => true]); + + self::assertSame(0, $tester->getStatusCode()); + + $records = $this->getAllRecords('tx_tracking_pageview'); + self::assertCount(1, $records); + + $records = $this->getAllRecords('tx_tracking_recordview'); + self::assertCount(1, $records); + + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(4, $records); + foreach ($records as $record) { + self::assertSame(1663773639, $record['crdate']); + } } } diff --git a/Tests/Functional/Dashboard/Provider/NewestPageviewsTest.php b/Tests/Functional/Dashboard/Provider/NewestPageviewsTest.php index 7ebdfcf..c0f4cab 100644 --- a/Tests/Functional/Dashboard/Provider/NewestPageviewsTest.php +++ b/Tests/Functional/Dashboard/Provider/NewestPageviewsTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,16 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand; 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 + * @covers \DanielSiepmann\Tracking\Dashboard\Provider\NewestPageviews */ class NewestPageviewsTest extends TestCase { @@ -51,10 +54,11 @@ class NewestPageviewsTest extends TestCase } $subject = new NewestPageviews( - GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview') + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand() ); - static::assertSame([ + self::assertSame([ 'Url 10 - User-Agent 10', 'Url 9 - User-Agent 9', 'Url 8 - User-Agent 8', @@ -81,10 +85,10 @@ class NewestPageviewsTest extends TestCase $subject = new NewestPageviews( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 2 + new Demand(31, 2) ); - static::assertSame([ + self::assertSame([ 'Url 10 - User-Agent 10', 'Url 9 - User-Agent 9', ], $subject->getItems()); @@ -107,11 +111,10 @@ class NewestPageviewsTest extends TestCase $subject = new NewestPageviews( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 6, - [9] + new Demand(31, 6, [9]) ); - static::assertSame([ + self::assertSame([ 'Url 10 - User-Agent 10', 'Url 8 - User-Agent 8', 'Url 7 - User-Agent 7', @@ -139,12 +142,10 @@ class NewestPageviewsTest extends TestCase $subject = new NewestPageviews( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 6, - [], - [1] + new Demand(31, 6, [], [1]) ); - static::assertSame([ + self::assertSame([ 'Url 9 - User-Agent 9', 'Url 7 - User-Agent 7', 'Url 5 - User-Agent 5', @@ -152,4 +153,6 @@ class NewestPageviewsTest extends TestCase 'Url 1 - User-Agent 1', ], $subject->getItems()); } + + // TODO: Add tests for new feature regarding tags } diff --git a/Tests/Functional/Dashboard/Provider/PageviewsPerDayTest.php b/Tests/Functional/Dashboard/Provider/PageviewsPerDayTest.php index acf8f09..307920f 100644 --- a/Tests/Functional/Dashboard/Provider/PageviewsPerDayTest.php +++ b/Tests/Functional/Dashboard/Provider/PageviewsPerDayTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,10 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand; +use DanielSiepmann\Tracking\Dashboard\Provider\Demand\Tag; use DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Localization\LanguageService; @@ -28,7 +32,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay + * @covers \DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerDay */ class PageviewsPerDayTest extends TestCase { @@ -51,12 +55,13 @@ class PageviewsPerDayTest extends TestCase $subject = new PageviewsPerDay( GeneralUtility::makeInstance(LanguageService::class), - GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview') + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand() ); $result = $subject->getChartData(); - static::assertCount(32, $result['labels']); - static::assertCount(32, $result['datasets'][0]['data']); + self::assertCount(32, $result['labels']); + self::assertCount(32, $result['datasets'][0]['data']); } /** @@ -76,12 +81,12 @@ class PageviewsPerDayTest extends TestCase $subject = new PageviewsPerDay( GeneralUtility::makeInstance(LanguageService::class), GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 3 + new Demand(3) ); $result = $subject->getChartData(); - static::assertCount(4, $result['labels']); - static::assertSame([ + self::assertCount(4, $result['labels']); + self::assertSame([ 1, 1, 1, @@ -106,13 +111,12 @@ class PageviewsPerDayTest extends TestCase $subject = new PageviewsPerDay( GeneralUtility::makeInstance(LanguageService::class), GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 3, - [2] + new Demand(3, 0, [2]) ); $result = $subject->getChartData(); - static::assertCount(4, $result['labels']); - static::assertSame([ + self::assertCount(4, $result['labels']); + self::assertSame([ 1, 0, 1, @@ -131,18 +135,16 @@ class PageviewsPerDayTest extends TestCase $subject = new PageviewsPerDay( GeneralUtility::makeInstance(LanguageService::class), GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 1, - [], - [], + new Demand(1, 0, [], []), 'd.m.Y' ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ date('d.m.Y', strtotime('-1 day')), date('d.m.Y'), ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -162,13 +164,11 @@ class PageviewsPerDayTest extends TestCase $subject = new PageviewsPerDay( GeneralUtility::makeInstance(LanguageService::class), GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 11, - [], - [1] + new Demand(11, 0, [], [1]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 0 => 0, 1 => 0, 2 => 1, @@ -183,4 +183,140 @@ class PageviewsPerDayTest extends TestCase 11 => 0, ], $result['datasets'][0]['data']); } + + /** + * @test + */ + public function respectedConfiguredTagRuleToNotIncludeBots(): void + { + $connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview'); + for ($i = 1; $i <= 10; $i++) { + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i * 20, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i * 20, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i * 300, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i * 300, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'yes', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + } + + $subject = new PageviewsPerDay( + GeneralUtility::makeInstance(LanguageService::class), + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand(2, 0, [], [], [ + Tag::createFromArray([ + 'name' => 'bot', + 'value' => 'no', + ]), + ]) + ); + + $result = $subject->getChartData(); + self::assertSame([ + 0 => 2, + 1 => 2, + 2 => 0, + ], $result['datasets'][0]['data']); + } + + /** + * @test + */ + public function respectedConfiguredTagRuleToIncludeBots(): void + { + $connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview'); + for ($i = 1; $i <= 10; $i++) { + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i * 20, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i * 20, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i * 300, + 'crdate' => strtotime('-' . $i . ' days'), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'record_uid' => $i * 300, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'yes', + 'crdate' => strtotime('-' . $i . ' days'), + ]); + } + + $subject = new PageviewsPerDay( + GeneralUtility::makeInstance(LanguageService::class), + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand(2, 0, [], [], [ + Tag::createFromArray([ + 'name' => 'bot', + 'value' => 'yes', + ]), + ]) + ); + + $result = $subject->getChartData(); + self::assertSame([ + 0 => 1, + 1 => 1, + 2 => 0, + ], $result['datasets'][0]['data']); + } } diff --git a/Tests/Functional/Dashboard/Provider/PageviewsPerOperatingSystemTest.php b/Tests/Functional/Dashboard/Provider/PageviewsPerOperatingSystemTest.php index 2adbbe2..c288d79 100644 --- a/Tests/Functional/Dashboard/Provider/PageviewsPerOperatingSystemTest.php +++ b/Tests/Functional/Dashboard/Provider/PageviewsPerOperatingSystemTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,16 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand; 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 + * @covers \DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerOperatingSystem */ class PageviewsPerOperatingSystemTest extends TestCase { @@ -41,20 +44,36 @@ class PageviewsPerOperatingSystemTest extends TestCase public function listsSixResultsForLast31DaysByDefault(): void { $connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview'); + $connection->insert('tx_tracking_pageview', [ + 'pid' => 1, + 'crdate' => time(), + ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => 1, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System ' . 1, + ]); for ($i = 1; $i <= 10; $i++) { $connection->insert('tx_tracking_pageview', [ 'pid' => $i, - 'operating_system' => 'System ' . $i, 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System ' . $i, + ]); } $subject = new PageviewsPerOperatingSystem( - GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview') + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand() ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'System 1', 'System 10', 'System 2', @@ -62,7 +81,14 @@ class PageviewsPerOperatingSystemTest extends TestCase 'System 4', 'System 5', ], $result['labels']); - static::assertCount(6, $result['datasets'][0]['data']); + self::assertSame([ + '2', + '1', + '1', + '1', + '1', + '1', + ], array_map('strval', $result['datasets'][0]['data'])); } /** @@ -74,36 +100,61 @@ class PageviewsPerOperatingSystemTest extends TestCase $connection = $this->getConnectionPool()->getConnectionForTable('tx_tracking_pageview'); $connection->insert('tx_tracking_pageview', [ 'pid' => 1, - 'operating_system' => 'System 1', 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 1', + ]); $connection->insert('tx_tracking_pageview', [ 'pid' => 2, - 'operating_system' => 'System 2', 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 2', + ]); $connection->insert('tx_tracking_pageview', [ 'pid' => 3, - 'operating_system' => 'System 3', 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '3', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 3', + ]); $connection->insert('tx_tracking_pageview', [ - 'pid' => 2, - 'operating_system' => 'System 2', + 'pid' => 3, 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '4', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 2', + ]); $subject = new PageviewsPerOperatingSystem( - GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview') + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + new Demand() ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'System 2', 'System 1', 'System 3', ], $result['labels']); - static::assertCount(3, $result['datasets'][0]['data']); + self::assertSame([ + '2', + '1', + '1', + ], array_map('strval', $result['datasets'][0]['data'])); } /** @@ -115,31 +166,49 @@ class PageviewsPerOperatingSystemTest extends TestCase $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_tag', [ + 'record_uid' => '1', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 1', + ]); $connection->insert('tx_tracking_pageview', [ 'pid' => 2, - 'operating_system' => 'System 2', 'crdate' => strtotime('-2 days'), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '2', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 2', + ]); $connection->insert('tx_tracking_pageview', [ 'pid' => 3, - 'operating_system' => 'System 3', 'crdate' => strtotime('-1 days'), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => '3', + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System 3', + ]); $subject = new PageviewsPerOperatingSystem( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 2 + new Demand(2) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'System 2', 'System 3', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertSame([ + '1', + '1', + ], array_map('strval', $result['datasets'][0]['data'])); } /** @@ -152,25 +221,34 @@ class PageviewsPerOperatingSystemTest extends TestCase for ($i = 1; $i <= 10; $i++) { $connection->insert('tx_tracking_pageview', [ 'pid' => $i, - 'operating_system' => 'System ' . $i, 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System ' . $i, + ]); } $subject = new PageviewsPerOperatingSystem( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 31, - 4 + new Demand(31, 4) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'System 1', 'System 10', 'System 2', 'System 3', ], $result['labels']); - static::assertCount(4, $result['datasets'][0]['data']); + self::assertSame([ + '1', + '1', + '1', + '1', + ], array_map('strval', $result['datasets'][0]['data'])); } /** @@ -184,26 +262,37 @@ class PageviewsPerOperatingSystemTest extends TestCase $connection->insert('tx_tracking_pageview', [ 'pid' => $i, 'sys_language_uid' => $i % 2, - 'operating_system' => 'System ' . $i, 'crdate' => time(), ]); + $connection->insert('tx_tracking_tag', [ + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'os', + 'value' => 'System ' . $i, + ]); } $subject = new PageviewsPerOperatingSystem( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - 31, - 6, - [1] + new Demand(31, 6, [], [1]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'System 1', 'System 3', 'System 5', 'System 7', 'System 9', ], $result['labels']); - static::assertCount(5, $result['datasets'][0]['data']); + self::assertSame([ + '1', + '1', + '1', + '1', + '1', + ], array_map('strval', $result['datasets'][0]['data'])); } + + // TODO: Add tests for new feature regarding tags } diff --git a/Tests/Functional/Dashboard/Provider/PageviewsPerPageTest.php b/Tests/Functional/Dashboard/Provider/PageviewsPerPageTest.php index 74084de..555db45 100644 --- a/Tests/Functional/Dashboard/Provider/PageviewsPerPageTest.php +++ b/Tests/Functional/Dashboard/Provider/PageviewsPerPageTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,10 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand; +use DanielSiepmann\Tracking\Dashboard\Provider\Demand\Tag; use DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Domain\Repository\PageRepository; @@ -28,7 +32,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage + * @covers \DanielSiepmann\Tracking\Dashboard\Provider\PageviewsPerPage */ class PageviewsPerPageTest extends TestCase { @@ -46,17 +50,19 @@ class PageviewsPerPageTest extends TestCase for ($i = 1; $i <= 10; $i++) { $connection->insert('tx_tracking_pageview', [ 'pid' => $i, + 'uid' => $i, 'crdate' => time(), ]); } $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - GeneralUtility::makeInstance(PageRepository::class) + GeneralUtility::makeInstance(PageRepository::class), + new Demand() ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 10', 'Page 9', 'Page 8', @@ -64,7 +70,7 @@ class PageviewsPerPageTest extends TestCase 'Page 6', 'Page 5', ], $result['labels']); - static::assertCount(6, $result['datasets'][0]['data']); + self::assertCount(6, $result['datasets'][0]['data']); } /** @@ -93,16 +99,17 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), - GeneralUtility::makeInstance(PageRepository::class) + GeneralUtility::makeInstance(PageRepository::class), + new Demand() ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 2', 'Page 3', 'Page 1', ], $result['labels']); - static::assertCount(3, $result['datasets'][0]['data']); + self::assertCount(3, $result['datasets'][0]['data']); } /** @@ -128,15 +135,15 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), GeneralUtility::makeInstance(PageRepository::class), - 2 + new Demand(2) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 3', 'Page 2', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -156,18 +163,17 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), GeneralUtility::makeInstance(PageRepository::class), - 31, - 4 + new Demand(31, 4) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 10', 'Page 9', 'Page 8', 'Page 7', ], $result['labels']); - static::assertCount(4, $result['datasets'][0]['data']); + self::assertCount(4, $result['datasets'][0]['data']); } /** @@ -187,19 +193,17 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), GeneralUtility::makeInstance(PageRepository::class), - 31, - 6, - [1, 2, 3, 4, 5, 6] + new Demand(31, 6, [1, 2, 3, 4, 5, 6]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 10', 'Page 9', 'Page 8', 'Page 7', ], $result['labels']); - static::assertCount(4, $result['datasets'][0]['data']); + self::assertCount(4, $result['datasets'][0]['data']); } /** @@ -235,18 +239,15 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), GeneralUtility::makeInstance(PageRepository::class), - 31, - 6, - [], - [1] + new Demand(31, 6, [], [1]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 2', 'Page 1', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -282,18 +283,141 @@ class PageviewsPerPageTest extends TestCase $subject = new PageviewsPerPage( GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), GeneralUtility::makeInstance(PageRepository::class), - 31, - 6, - [], - [1, '0'] + new Demand(31, 6, [], [1, 0]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Page 2', 'Page 1', 'Page 3', ], $result['labels']); - static::assertCount(3, $result['datasets'][0]['data']); + self::assertCount(3, $result['datasets'][0]['data']); + } + + /** + * @test + */ + public function respectedConfiguredTagRuleToNotIncludeBots(): 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, + 'uid' => $i, + 'crdate' => time(), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'uid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => time(), + ]); + } + for ($i = 11; $i <= 20; $i++) { + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i, + 'crdate' => time(), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'uid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'yes', + 'crdate' => time(), + ]); + } + + $subject = new PageviewsPerPage( + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + GeneralUtility::makeInstance(PageRepository::class), + new Demand(31, 6, [], [], [ + Tag::createFromArray([ + 'name' => 'bot', + 'value' => 'no', + ]), + ]) + ); + + $result = $subject->getChartData(); + self::assertSame([ + 'Page 10', + 'Page 9', + 'Page 8', + 'Page 7', + 'Page 6', + 'Page 5', + ], $result['labels']); + self::assertCount(6, $result['datasets'][0]['data']); + } + + /** + * @test + */ + public function respectedConfiguredTagRuleToIncludeBots(): 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, + 'uid' => $i, + 'crdate' => time(), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'uid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'no', + 'crdate' => time(), + ]); + } + for ($i = 11; $i <= 20; $i++) { + $connection->insert('tx_tracking_pageview', [ + 'pid' => $i, + 'uid' => $i, + 'crdate' => time(), + ]); + $connection->insert('tx_tracking_tag', [ + 'pid' => $i, + 'uid' => $i, + 'record_uid' => $i, + 'record_table_name' => 'tx_tracking_pageview', + 'name' => 'bot', + 'value' => 'yes', + 'crdate' => time(), + ]); + } + + $subject = new PageviewsPerPage( + GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tracking_pageview'), + GeneralUtility::makeInstance(PageRepository::class), + new Demand(31, 6, [], [], [ + Tag::createFromArray([ + 'name' => 'bot', + 'value' => 'yes', + ]), + ]) + ); + + $result = $subject->getChartData(); + self::assertSame([ + 'Page 20', + 'Page 19', + 'Page 18', + 'Page 17', + 'Page 16', + 'Page 15', + ], $result['labels']); + self::assertCount(6, $result['datasets'][0]['data']); } } diff --git a/Tests/Functional/Dashboard/Provider/RecordviewsTest.php b/Tests/Functional/Dashboard/Provider/RecordviewsTest.php index 79d4dbe..ee7c337 100644 --- a/Tests/Functional/Dashboard/Provider/RecordviewsTest.php +++ b/Tests/Functional/Dashboard/Provider/RecordviewsTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,16 @@ namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional\Dashboard\Provider; + +use DanielSiepmann\Tracking\Dashboard\Provider\Demand; use DanielSiepmann\Tracking\Dashboard\Provider\Recordviews; 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 + * @covers \DanielSiepmann\Tracking\Dashboard\Provider\Recordviews */ class RecordviewsTest extends TestCase { @@ -53,11 +56,12 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), - $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview') + $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), + new Demand() ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 10', 'Category 9', 'Category 8', @@ -65,7 +69,7 @@ class RecordviewsTest extends TestCase 'Category 6', 'Category 5', ], $result['labels']); - static::assertCount(6, $result['datasets'][0]['data']); + self::assertCount(6, $result['datasets'][0]['data']); } /** @@ -103,16 +107,16 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 2 + new Demand(2) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 2', 'Category 3', 'Category 1', ], $result['labels']); - static::assertCount(3, $result['datasets'][0]['data']); + self::assertCount(3, $result['datasets'][0]['data']); } /** @@ -144,15 +148,15 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 2 + new Demand(2) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 3', 'Category 2', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -174,16 +178,15 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 2 + new Demand(31, 2) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 10', 'Category 9', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -206,20 +209,18 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 6, - [1, 2, 3, 4, 5] + new Demand(31, 6, [1, 2, 3, 4, 5]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 10', 'Category 9', 'Category 8', 'Category 7', 'Category 6', ], $result['labels']); - static::assertCount(5, $result['datasets'][0]['data']); + self::assertCount(5, $result['datasets'][0]['data']); } /** @@ -247,20 +248,17 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 6, - [], - [], + new Demand(31, 6), ['sys_category'] ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 3', 'Category 2', 'Category 1', ], $result['labels']); - static::assertCount(3, $result['datasets'][0]['data']); + self::assertCount(3, $result['datasets'][0]['data']); } /** @@ -286,20 +284,17 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 6, - [], - [], + new Demand(31, 6), [], ['1', 2] ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Content element 2', 'Content element 1', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -334,20 +329,15 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 6, - [], - [1], - [], - [] + new Demand(31, 6, [], [1]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 2', 'Kategorie 1', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } /** @@ -382,19 +372,16 @@ class RecordviewsTest extends TestCase $subject = new Recordviews( GeneralUtility::makeInstance(PageRepository::class), $this->getConnectionPool()->getQueryBuilderForTable('tx_tracking_recordview'), - 31, - 6, - [], - [1, 0], - [], - [] + new Demand(31, 6, [], [1, 0]) ); $result = $subject->getChartData(); - static::assertSame([ + self::assertSame([ 'Category 1', 'Category 2', ], $result['labels']); - static::assertCount(2, $result['datasets'][0]['data']); + self::assertCount(2, $result['datasets'][0]['data']); } + + // TODO: Add tests for new feature regarding tags } diff --git a/Tests/Functional/Domain/Extractors/BotsTest.php b/Tests/Functional/Domain/Extractors/BotsTest.php new file mode 100644 index 0000000..8a92f09 --- /dev/null +++ b/Tests/Functional/Domain/Extractors/BotsTest.php @@ -0,0 +1,183 @@ + + * + * 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\Tests\Functional\Domain\Extractors; + +use DanielSiepmann\Tracking\Domain\Extractors\Bots; +use DanielSiepmann\Tracking\Domain\Extractors\Bots\CustomBotParser; +use DanielSiepmann\Tracking\Domain\Model\Extractor; +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; +use DeviceDetector\DeviceDetector; +use Prophecy\PhpUnit\ProphecyTrait; +use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; + +/** + * @covers \DanielSiepmann\Tracking\Domain\Extractors\Bots + */ +class BotsTest extends TestCase +{ + use ProphecyTrait; + + protected $testExtensionsToLoad = [ + 'typo3conf/ext/tracking', + ]; + + /** + * @test + * @dataProvider possibleUserStringWithBots + * @testdox Bot $expectedBot is extracted from Pageview UserAgent string: $userAgent + */ + public function returnsBotForPageview(string $userAgent, string $expectedBot): void + { + $model = $this->prophesize(Pageview::class); + $model->getUserAgent()->willReturn($userAgent); + + $extractor = new Bots(new CustomBotParser()); + $tags = $extractor->extractTagFromPageview($model->reveal()); + + self::assertCount(2, $tags); + self::assertSame('bot', $tags[0]->getName()); + self::assertSame('yes', $tags[0]->getValue()); + self::assertSame('bot_name', $tags[1]->getName()); + self::assertSame($expectedBot, $tags[1]->getValue()); + } + + /** + * @test + * @dataProvider possibleUserStringWithBots + * @testdox Bot $expectedBot is extracted from Recordview UserAgent string: $userAgent + */ + public function returnsBotForRecordview(string $userAgent, string $expectedBot): void + { + $model = $this->prophesize(Recordview::class); + $model->getUserAgent()->willReturn($userAgent); + + $extractor = new Bots(new CustomBotParser()); + $tags = $extractor->extractTagFromRecordview($model->reveal()); + + self::assertCount(2, $tags); + self::assertSame('bot', $tags[0]->getName()); + self::assertSame('yes', $tags[0]->getValue()); + self::assertSame('bot_name', $tags[1]->getName()); + self::assertSame($expectedBot, $tags[1]->getValue()); + } + + public function possibleUserStringWithBots(): array + { + return [ + 0 => [ + 'userAgent' => 'nettle (+https://www.nettle.sk)', + 'expectedBot' => 'Nettle', + ], + 1 => [ + 'userAgent' => 'MauiBot (crawler.feedback+wc@gmail.com)', + 'expectedBot' => 'Generic Bot', + ], + 2 => [ + 'userAgent' => 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)', + 'expectedBot' => 'Facebook External Hit', + ], + 3 => [ + 'userAgent' => 'Java/11.0.10', + 'expectedBot' => 'Java', + ], + 4 => [ + 'userAgent' => 'newspaper/0.2.8', + 'expectedBot' => 'Newspaper', + ], + 5 => [ + 'userAgent' => 'Tiny Tiny RSS/21.05-326850845 (http://tt-rss.org/)', + 'expectedBot' => 'Tiny Tiny RSS', + ], + 6 => [ + 'userAgent' => 'BacklinkCrawler (http://www.backlinktest.com/crawler.html)', + 'expectedBot' => 'BacklinkCrawler', + ], + 7 => [ + 'userAgent' => 'CCBot/2.0 (https://commoncrawl.org/faq/)', + 'expectedBot' => 'ccBot crawler', + ], + 8 => [ + 'userAgent' => 'Tiny Tiny RSS/21.04-e8f78181f (http://tt-rss.org/)', + 'expectedBot' => 'Tiny Tiny RSS', + ], + 9 => [ + 'userAgent' => 'ltx71 - (http://ltx71.com/)', + 'expectedBot' => 'LTX71', + ], + 10 => [ + 'userAgent' => 'FeedFetcher-Google; (+http://www.google.com/feedfetcher.html)', + 'expectedBot' => 'Googlebot', + ], + 11 => [ + 'userAgent' => 'colly - https://github.com/gocolly/colly', + 'expectedBot' => 'colly', + ], + 12 => [ + 'userAgent' => 'WordPress.com; https://serdargunes.wordpress.com', + 'expectedBot' => 'WordPress', + ], + 13 => [ + 'userAgent' => 'Tiny Tiny RSS/21.03-2f402d598 (http://tt-rss.org/)', + 'expectedBot' => 'Tiny Tiny RSS', + ], + 14 => [ + 'userAgent' => 'netEstate NE Crawler (+http://www.website-datenbank.de/)', + 'expectedBot' => 'netEstate', + ], + 15 => [ + 'userAgent' => 'python-requests/2.18.1', + 'expectedBot' => 'Python Requests', + ], + 16 => [ + 'userAgent' => 'PocketParser/2.0 (+https://getpocket.com/pocketparser_ua)', + 'expectedBot' => 'PocketParser', + ], + 17 => [ + 'userAgent' => 'Faraday v0.17.3', + 'expectedBot' => 'Faraday', + ], + 18 => [ + 'userAgent' => 'hgfAlphaXCrawl/0.1 (+https://www.fim.uni-passau.de/data-science/forschung/open-search)', + 'expectedBot' => 'Generic Bot', + ], + 19 => [ + 'userAgent' => 'Upflow/1.0', + 'expectedBot' => 'Upflow', + ], + 20 => [ + 'userAgent' => 'crusty/0.12.0', + 'expectedBot' => 'Crusty', + ], + 21 => [ + 'userAgent' => 'TelegramBot (like TwitterBot)', + 'expectedBot' => 'TelegramBot', + ], + 22 => [ + 'userAgent' => 'python-requests/2.25.1', + 'expectedBot' => 'Python Requests', + ], + ]; + } +} diff --git a/Tests/Functional/Domain/Recordview/FactoryTest.php b/Tests/Functional/Domain/Recordview/FactoryTest.php index a1977e2..6231458 100644 --- a/Tests/Functional/Domain/Recordview/FactoryTest.php +++ b/Tests/Functional/Domain/Recordview/FactoryTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,8 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Recordview; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Recordview; + use DanielSiepmann\Tracking\Domain\Model\RecordRule; use DanielSiepmann\Tracking\Domain\Model\Recordview; use DanielSiepmann\Tracking\Domain\Recordview\Factory; @@ -31,7 +33,7 @@ use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Recordview\Factory + * @covers \DanielSiepmann\Tracking\Domain\Recordview\Factory */ class FactoryTest extends FunctionalTestCase { @@ -67,7 +69,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertInstanceOf(Recordview::class, $result); + self::assertInstanceOf(Recordview::class, $result); } /** @@ -96,7 +98,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame('Some User Agent', $result->getUserAgent()); + self::assertSame('Some User Agent', $result->getUserAgent()); } /** @@ -125,7 +127,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame('https://example.com', $result->getUrl()); + self::assertSame('https://example.com', $result->getUrl()); } /** @@ -154,7 +156,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertInstanceOf(\DateTimeImmutable::class, $result->getCrdate()); + self::assertInstanceOf(\DateTimeImmutable::class, $result->getCrdate()); } /** @@ -183,7 +185,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame($language->reveal(), $result->getLanguage()); + self::assertSame($language->reveal(), $result->getLanguage()); } /** @@ -212,7 +214,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame(10, $result->getPageUid()); + self::assertSame(10, $result->getPageUid()); } /** @@ -241,7 +243,7 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame(20, $result->getRecordUid()); + self::assertSame(20, $result->getRecordUid()); } /** @@ -270,6 +272,6 @@ class FactoryTest extends FunctionalTestCase $subject = $this->get(Factory::class); $result = $subject->fromRequest($request->reveal(), $rule->reveal()); - static::assertSame('sys_category', $result->getTableName()); + self::assertSame('sys_category', $result->getTableName()); } } diff --git a/Tests/Functional/Fixtures/Pages.xml b/Tests/Functional/Fixtures/Pages.xml index 20d3076..103fb79 100644 --- a/Tests/Functional/Fixtures/Pages.xml +++ b/Tests/Functional/Fixtures/Pages.xml @@ -58,4 +58,54 @@ 10 Page 10 + + 1 + 12 + Page 12 + + + 1 + 13 + Page 13 + + + 1 + 14 + Page 14 + + + 1 + 15 + Page 15 + + + 1 + 16 + Page 16 + + + 1 + 17 + Page 17 + + + 1 + 18 + Page 18 + + + 1 + 19 + Page 19 + + + 1 + 20 + Page 20 + + + 1 + 21 + Page 21 + diff --git a/Tests/Functional/Fixtures/Typo3FeaturesTest/PageWithRecords.xml b/Tests/Functional/Fixtures/Typo3FeaturesTest/PageWithRecords.xml index 6167f58..83a167e 100644 --- a/Tests/Functional/Fixtures/Typo3FeaturesTest/PageWithRecords.xml +++ b/Tests/Functional/Fixtures/Typo3FeaturesTest/PageWithRecords.xml @@ -10,7 +10,6 @@ 1 https://example.com/path Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 - 1 diff --git a/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml b/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml deleted file mode 100644 index 88a86ea..0000000 --- a/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithMissingOperatingSystem.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 0 - 1 - - - - 1 - 1 - https://example.com/path - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 - - - - 1 - 2 - https://example.com/path - Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001) - - - diff --git a/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml b/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml deleted file mode 100644 index e8cb0ae..0000000 --- a/Tests/Functional/Fixtures/UpdateDataCommandTest/PageviewsWithOperatingSystem.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 0 - 1 - - - - 1 - 1 - https://example.com/path - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 - Linux - - - 1 - 2 - https://example.com/path - Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001) - Android - - diff --git a/Tests/Functional/Fixtures/UpdateDataCommandTest/WithCompatibleVersion.xml b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithCompatibleVersion.xml new file mode 100644 index 0000000..fa891de --- /dev/null +++ b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithCompatibleVersion.xml @@ -0,0 +1,68 @@ + + + + 0 + 1 + + + + 1 + 1 + 1630649915 + 0 + https://example.com/path + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 + v2.0.0 + + + 1 + 1 + 1630649915 + 0 + https://example.com/path + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 + 1 + sys_category + v2.0.0 + + + 1 + 1 + 1663773639 + 1 + tx_tracking_pageview + bot + no + v2.0.0 + + + 1 + v2 + 1663773639 + 1 + tx_tracking_pageview + os + Linux + v2.0.0 + + + 1 + 3 + 1663773639 + 1 + tx_tracking_recordview + bot + no + v2.0.0 + + + 1 + 4 + 1663773639 + 1 + tx_tracking_recordview + os + Linux + v2.0.0 + + diff --git a/Tests/Functional/Fixtures/UpdateDataCommandTest/WithMissingOperatingSystem.xml b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithMissingOperatingSystem.xml new file mode 100644 index 0000000..26a472f --- /dev/null +++ b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithMissingOperatingSystem.xml @@ -0,0 +1,48 @@ + + + + 0 + 1 + + + + 1 + 1 + 1630649915 + 1630649915 + 0 + https://example.com/path + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 + + + 1 + 2 + 1630649916 + 1630649916 + 0 + https://example.com/path + Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001) + + + 1 + 1 + 1630649915 + 1630649915 + 0 + https://example.com/path + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 + 1 + sys_category + + + 1 + 2 + 1630649916 + 1630649916 + 0 + https://example.com/path + Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001) + 1 + sys_category + + diff --git a/Tests/Functional/Fixtures/UpdateDataCommandTest/WithOperatingSystem.xml b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithOperatingSystem.xml new file mode 100644 index 0000000..198d18b --- /dev/null +++ b/Tests/Functional/Fixtures/UpdateDataCommandTest/WithOperatingSystem.xml @@ -0,0 +1,50 @@ + + + + 0 + 1 + + + + 1 + 1 + 1630649915 + 1630649915 + 0 + https://example.com/path + Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36 + + + 1 + 1 + 1630649915 + 1630649915 + 0 + 1 + tx_tracking_pageview + os + Linux + 2.0.0 + + + 1 + 2 + 1630649916 + 1630649916 + 0 + https://example.com/path + Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3003 Build/PKQ1.181203.001) + + + 1 + 2 + 1630649916 + 1630649916 + 0 + 2 + tx_tracking_pageview + os + Android + 2.0.0 + + diff --git a/Tests/Functional/PageviewTest.php b/Tests/Functional/PageviewTest.php index 6e9e34d..a5b1284 100644 --- a/Tests/Functional/PageviewTest.php +++ b/Tests/Functional/PageviewTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,8 @@ namespace DanielSiepmann\Tracking\Tests\Functional; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional; + use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; @@ -62,12 +64,68 @@ class PageviewTest extends TestCase $records = $this->getAllRecords('tx_tracking_pageview'); self::assertCount(1, $records); - self::assertSame('1', (string)$records[0]['pid']); - self::assertSame('1', (string)$records[0]['uid']); + self::assertSame(1, $records[0]['pid']); + self::assertSame(1, $records[0]['uid']); self::assertSame('http://localhost/?id=1', $records[0]['url']); self::assertSame('Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0', $records[0]['user_agent']); - self::assertSame('Macintosh', $records[0]['operating_system']); self::assertSame('0', (string)$records[0]['type']); + + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(2, $records); + + self::assertSame(1, $records[0]['pid']); + self::assertSame(1, $records[0]['record_uid']); + self::assertSame('tx_tracking_pageview', $records[0]['record_table_name']); + self::assertSame('bot', $records[0]['name']); + self::assertSame('no', $records[0]['value']); + + self::assertSame(1, $records[1]['pid']); + self::assertSame(1, $records[1]['record_uid']); + self::assertSame('tx_tracking_pageview', $records[1]['record_table_name']); + self::assertSame('os', $records[1]['name']); + self::assertSame('Macintosh', $records[1]['value']); + } + + /** + * @test + */ + public function trackedWithBotResolvedToTags(): void + { + $request = new InternalRequest(); + $request = $request->withPageId(1); + $request = $request->withHeader('User-Agent', 'Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)'); + $response = $this->executeFrontendRequest($request); + + self::assertSame(200, $response->getStatusCode()); + + $records = $this->getAllRecords('tx_tracking_pageview'); + self::assertCount(1, $records); + self::assertSame(1, $records[0]['pid']); + self::assertSame(1, $records[0]['uid']); + self::assertSame('http://localhost/?id=1', $records[0]['url']); + self::assertSame('Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)', $records[0]['user_agent']); + self::assertSame('0', (string)$records[0]['type']); + + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(3, $records); + + self::assertSame(1, $records[0]['pid']); + self::assertSame(1, $records[0]['record_uid']); + self::assertSame('tx_tracking_pageview', $records[0]['record_table_name']); + self::assertSame('bot', $records[0]['name']); + self::assertSame('yes', $records[0]['value']); + + self::assertSame(1, $records[1]['pid']); + self::assertSame(1, $records[1]['record_uid']); + self::assertSame('tx_tracking_pageview', $records[1]['record_table_name']); + self::assertSame('bot_name', $records[1]['name']); + self::assertSame('Slackbot', $records[1]['value']); + + self::assertSame(1, $records[2]['pid']); + self::assertSame(1, $records[2]['record_uid']); + self::assertSame('tx_tracking_pageview', $records[2]['record_table_name']); + self::assertSame('os', $records[2]['name']); + self::assertSame('Unkown', $records[2]['value']); } /** @@ -85,7 +143,7 @@ class PageviewTest extends TestCase self::assertSame(200, $response->getStatusCode()); - $records = $this->getAllRecords('tx_tracking_pageview'); - self::assertCount(0, $records); + self::assertCount(0, $this->getAllRecords('tx_tracking_pageview')); + self::assertCount(0, $this->getAllRecords('tx_tracking_tag')); } } diff --git a/Tests/Functional/RecordviewTest.php b/Tests/Functional/RecordviewTest.php index ce72cf0..2514058 100644 --- a/Tests/Functional/RecordviewTest.php +++ b/Tests/Functional/RecordviewTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,8 @@ namespace DanielSiepmann\Tracking\Tests\Functional; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional; + use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest; use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; @@ -54,6 +56,7 @@ class RecordviewTest extends TestCase */ public function trackedWhenAllowed(): void { + $this->setUpBackendUserFromFixture(1); $request = new InternalRequest(); $request = $request->withPageId(1); $request = $request->withQueryParameter('topic_id', 1); @@ -64,14 +67,28 @@ class RecordviewTest extends TestCase $records = $this->getAllRecords('tx_tracking_recordview'); self::assertCount(1, $records); - self::assertSame('1', (string)$records[0]['pid']); - self::assertSame('1', (string)$records[0]['uid']); + self::assertSame(1, $records[0]['pid']); + self::assertSame(1, $records[0]['uid']); self::assertSame('http://localhost/?id=1&topic_id=1', $records[0]['url']); self::assertSame('Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0', $records[0]['user_agent']); - self::assertSame('Macintosh', $records[0]['operating_system']); self::assertSame('sys_category_1', $records[0]['record']); - self::assertSame('1', (string)$records[0]['record_uid']); + self::assertSame(1, $records[0]['record_uid']); self::assertSame('sys_category', $records[0]['record_table_name']); + + $records = $this->getAllRecords('tx_tracking_tag'); + self::assertCount(4, $records); + + self::assertSame(1, $records[2]['pid']); + self::assertSame(1, $records[2]['record_uid']); + self::assertSame('tx_tracking_recordview', $records[2]['record_table_name']); + self::assertSame('bot', $records[2]['name']); + self::assertSame('no', $records[2]['value']); + + self::assertSame(1, $records[3]['pid']); + self::assertSame(1, $records[3]['record_uid']); + self::assertSame('tx_tracking_recordview', $records[3]['record_table_name']); + self::assertSame('os', $records[3]['name']); + self::assertSame('Macintosh', $records[3]['value']); } /** diff --git a/Tests/Functional/Typo3FeaturesTest.php b/Tests/Functional/Typo3FeaturesTest.php index 95e5864..3d1f246 100644 --- a/Tests/Functional/Typo3FeaturesTest.php +++ b/Tests/Functional/Typo3FeaturesTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,15 @@ namespace DanielSiepmann\Tracking\Tests\Functional; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Functional; + use DanielSiepmann\Tracking\Functional\CopyingPageWithRecordsWorks; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\Localization\LanguageServiceFactory; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase; /** - * @covers \DanielSiepmann\Tracking\Functional\CopyingPageWithRecordsWorks + * @covers \DanielSiepmann\Tracking\Hooks\DataHandler * @testdox This extension works with TYPO3 feature: */ class Typo3FeaturesTest extends TestCase diff --git a/Tests/Unit/Domain/Model/ExtractorTest.php b/Tests/Unit/Domain/Extractors/OperatingSystemTest.php similarity index 67% rename from Tests/Unit/Domain/Model/ExtractorTest.php rename to Tests/Unit/Domain/Extractors/OperatingSystemTest.php index 740330e..11bc74c 100644 --- a/Tests/Unit/Domain/Model/ExtractorTest.php +++ b/Tests/Unit/Domain/Extractors/OperatingSystemTest.php @@ -1,6 +1,6 @@ @@ -21,32 +21,54 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Extractors; + +use DanielSiepmann\Tracking\Domain\Extractors\OperatingSystem; use DanielSiepmann\Tracking\Domain\Model\Extractor; -use DanielSiepmann\Tracking\Domain\Model\HasUserAgent; +use DanielSiepmann\Tracking\Domain\Model\Pageview; +use DanielSiepmann\Tracking\Domain\Model\Recordview; use Prophecy\PhpUnit\ProphecyTrait; use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Model\Extractor + * @covers \DanielSiepmann\Tracking\Domain\Extractors\OperatingSystem */ -class ExtractorTest extends TestCase +class OperatingSystemTest extends TestCase { use ProphecyTrait; /** * @test * @dataProvider possibleUserStringWithOperatingSystems - * @testdox Operating system $expectedOperatingSystem is extracted from UserAgent string: $userAgent + * @testdox Operating system $expectedOperatingSystem is extracted from Pageview UserAgent string: $userAgent */ - public function returnsOperatingSystem(string $userAgent, string $expectedOperatingSystem): void + public function returnsOperatingSystemForPageview(string $userAgent, string $expectedOperatingSystem): void { - $model = $this->prophesize(HasUserAgent::class); + $model = $this->prophesize(Pageview::class); $model->getUserAgent()->willReturn($userAgent); - static::assertSame( - $expectedOperatingSystem, - Extractor::getOperatingSystem($model->reveal()) - ); + $extractor = new OperatingSystem(); + $tags = $extractor->extractTagFromPageview($model->reveal()); + + self::assertCount(1, $tags); + self::assertSame($expectedOperatingSystem, $tags[0]->getValue()); + } + + /** + * @test + * @dataProvider possibleUserStringWithOperatingSystems + * @testdox Operating system $expectedOperatingSystem is extracted from Recordview UserAgent string: $userAgent + */ + public function returnsOperatingSystemForRecordview(string $userAgent, string $expectedOperatingSystem): void + { + $model = $this->prophesize(Recordview::class); + $model->getUserAgent()->willReturn($userAgent); + + $extractor = new OperatingSystem(); + $tags = $extractor->extractTagFromRecordview($model->reveal()); + + self::assertCount(1, $tags); + self::assertSame($expectedOperatingSystem, $tags[0]->getValue()); } public function possibleUserStringWithOperatingSystems(): array @@ -62,11 +84,11 @@ class ExtractorTest extends TestCase ], [ 'userAgent' => 'Apache-HttpClient/4.5.2 (Java/1.8.0_151)', - 'expectedOperatingSystem' => '', + 'expectedOperatingSystem' => 'Unkown', ], [ 'userAgent' => 'AwarioSmartBot/1.0 (+https://awario.com/bots.html; bots@awario.com)', - 'expectedOperatingSystem' => '', + 'expectedOperatingSystem' => 'Unkown', ], [ 'userAgent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', diff --git a/Tests/Unit/Domain/Model/PageviewTest.php b/Tests/Unit/Domain/Model/PageviewTest.php index 780973d..b287fe9 100644 --- a/Tests/Unit/Domain/Model/PageviewTest.php +++ b/Tests/Unit/Domain/Model/PageviewTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,15 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; + use DanielSiepmann\Tracking\Domain\Model\Pageview; use Prophecy\PhpUnit\ProphecyTrait; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Model\Pageview + * @covers \DanielSiepmann\Tracking\Domain\Model\Pageview */ class PageviewTest extends TestCase { @@ -49,7 +51,7 @@ class PageviewTest extends TestCase '' ); - static::assertInstanceOf(Pageview::class, $subject); + self::assertInstanceOf(Pageview::class, $subject); } /** @@ -68,7 +70,7 @@ class PageviewTest extends TestCase '' ); - static::assertSame(500, $subject->getPageUid()); + self::assertSame(500, $subject->getPageUid()); } /** @@ -87,7 +89,7 @@ class PageviewTest extends TestCase '' ); - static::assertSame($language->reveal(), $subject->getLanguage()); + self::assertSame($language->reveal(), $subject->getLanguage()); } /** @@ -107,7 +109,7 @@ class PageviewTest extends TestCase '' ); - static::assertSame($crdate, $subject->getCrdate()); + self::assertSame($crdate, $subject->getCrdate()); } /** @@ -126,7 +128,7 @@ class PageviewTest extends TestCase '' ); - static::assertSame(999, $subject->getPageType()); + self::assertSame(999, $subject->getPageType()); } /** @@ -145,7 +147,7 @@ class PageviewTest extends TestCase '' ); - static::assertSame('https://example.com/path.html', $subject->getUrl()); + self::assertSame('https://example.com/path.html', $subject->getUrl()); } /** @@ -164,7 +166,7 @@ class PageviewTest extends TestCase 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0' ); - static::assertSame( + self::assertSame( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0', $subject->getUserAgent() ); @@ -186,7 +188,7 @@ class PageviewTest extends TestCase 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0' ); - static::assertSame( + self::assertSame( 0, $subject->getUid() ); @@ -209,31 +211,9 @@ class PageviewTest extends TestCase 10 ); - static::assertSame( + self::assertSame( 10, $subject->getUid() ); } - - /** - * @test - */ - public function returnsOperatingSystem(): void - { - $language = $this->prophesize(SiteLanguage::class); - - $subject = new Pageview( - 0, - $language->reveal(), - new \DateTimeImmutable(), - 0, - '', - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36' - ); - - static::assertSame( - 'Linux', - $subject->getOperatingSystem() - ); - } } diff --git a/Tests/Unit/Domain/Model/RecordRuleTest.php b/Tests/Unit/Domain/Model/RecordRuleTest.php index e61a5e3..0d4b7d5 100644 --- a/Tests/Unit/Domain/Model/RecordRuleTest.php +++ b/Tests/Unit/Domain/Model/RecordRuleTest.php @@ -1,6 +1,6 @@ @@ -21,11 +21,13 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; + use DanielSiepmann\Tracking\Domain\Model\RecordRule; use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Model\RecordRule + * @covers \DanielSiepmann\Tracking\Domain\Model\RecordRule */ class RecordRuleTest extends TestCase { @@ -40,7 +42,7 @@ class RecordRuleTest extends TestCase '' ); - static::assertInstanceOf(RecordRule::class, $subject); + self::assertInstanceOf(RecordRule::class, $subject); } /** @@ -55,7 +57,7 @@ class RecordRuleTest extends TestCase 'tableName' => '', ]); - static::assertInstanceOf(RecordRule::class, $subject); + self::assertInstanceOf(RecordRule::class, $subject); } /** @@ -76,9 +78,9 @@ class RecordRuleTest extends TestCase ], ]); - static::assertCount(2, $result); - static::assertInstanceOf(RecordRule::class, $result[0]); - static::assertInstanceOf(RecordRule::class, $result[1]); + self::assertCount(2, $result); + self::assertInstanceOf(RecordRule::class, $result[0]); + self::assertInstanceOf(RecordRule::class, $result[1]); } /** @@ -92,7 +94,7 @@ class RecordRuleTest extends TestCase '' ); - static::assertSame('match expression', $subject->getMatchesExpression()); + self::assertSame('match expression', $subject->getMatchesExpression()); } /** @@ -106,7 +108,7 @@ class RecordRuleTest extends TestCase '' ); - static::assertSame('match expression', $subject->getUidExpression()); + self::assertSame('match expression', $subject->getUidExpression()); } /** @@ -120,6 +122,6 @@ class RecordRuleTest extends TestCase 'table_name' ); - static::assertSame('table_name', $subject->getTableName()); + self::assertSame('table_name', $subject->getTableName()); } } diff --git a/Tests/Unit/Domain/Model/RecordviewTest.php b/Tests/Unit/Domain/Model/RecordviewTest.php index 20e0850..a7c06e9 100644 --- a/Tests/Unit/Domain/Model/RecordviewTest.php +++ b/Tests/Unit/Domain/Model/RecordviewTest.php @@ -1,6 +1,6 @@ @@ -21,13 +21,15 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Model; + use DanielSiepmann\Tracking\Domain\Model\Recordview; use Prophecy\PhpUnit\ProphecyTrait; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Model\Recordview + * @covers \DanielSiepmann\Tracking\Domain\Model\Recordview */ class RecordviewTest extends TestCase { @@ -50,7 +52,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertInstanceOf(Recordview::class, $subject); + self::assertInstanceOf(Recordview::class, $subject); } /** @@ -70,7 +72,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame(500, $subject->getPageUid()); + self::assertSame(500, $subject->getPageUid()); } /** @@ -90,7 +92,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame($language->reveal(), $subject->getLanguage()); + self::assertSame($language->reveal(), $subject->getLanguage()); } /** @@ -111,7 +113,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame($crdate, $subject->getCrdate()); + self::assertSame($crdate, $subject->getCrdate()); } /** @@ -131,7 +133,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame('https://example.com/path.html', $subject->getUrl()); + self::assertSame('https://example.com/path.html', $subject->getUrl()); } /** @@ -151,7 +153,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame( + self::assertSame( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0', $subject->getUserAgent() ); @@ -174,7 +176,7 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame( + self::assertSame( 10, $subject->getRecordUid() ); @@ -197,32 +199,9 @@ class RecordviewTest extends TestCase 'sys_category' ); - static::assertSame( + self::assertSame( 'sys_category', $subject->getTableName() ); } - - /** - * @test - */ - public function returnsOperatingSystem(): void - { - $language = $this->prophesize(SiteLanguage::class); - - $subject = new Recordview( - 0, - $language->reveal(), - new \DateTimeImmutable(), - '', - 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', - 10, - 'sys_category' - ); - - static::assertSame( - 'Linux', - $subject->getOperatingSystem() - ); - } } diff --git a/Tests/Unit/Domain/Pageview/FactoryTest.php b/Tests/Unit/Domain/Pageview/FactoryTest.php index 51b7966..97c978d 100644 --- a/Tests/Unit/Domain/Pageview/FactoryTest.php +++ b/Tests/Unit/Domain/Pageview/FactoryTest.php @@ -1,6 +1,6 @@ @@ -21,6 +21,8 @@ namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Pageview; * 02110-1301, USA. */ +namespace DanielSiepmann\Tracking\Tests\Unit\Domain\Pageview; + use DanielSiepmann\Tracking\Domain\Model\Pageview; use DanielSiepmann\Tracking\Domain\Pageview\Factory; use Prophecy\PhpUnit\ProphecyTrait; @@ -33,7 +35,7 @@ use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; /** - * @covers DanielSiepmann\Tracking\Domain\Pageview\Factory + * @covers \DanielSiepmann\Tracking\Domain\Pageview\Factory */ class FactoryTest extends TestCase { @@ -59,7 +61,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertInstanceOf(Pageview::class, $result); + self::assertInstanceOf(Pageview::class, $result); } /** @@ -84,7 +86,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertSame( + self::assertSame( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0', $result->getUserAgent() ); @@ -110,7 +112,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertSame( + self::assertSame( 'https://example.com/path?query=params&some=more#anchor', $result->getUrl() ); @@ -136,7 +138,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertSame( + self::assertSame( 50, $result->getPageType() ); @@ -162,7 +164,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertInstanceOf(\DateTimeImmutable::class, $result->getCrdate()); + self::assertInstanceOf(\DateTimeImmutable::class, $result->getCrdate()); } /** @@ -185,7 +187,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertInstanceOf(SiteLanguage::class, $result->getLanguage()); + self::assertInstanceOf(SiteLanguage::class, $result->getLanguage()); } /** @@ -208,7 +210,7 @@ class FactoryTest extends TestCase $subject = new Factory($this->prophesize(SiteFinder::class)->reveal()); $result = $subject->fromRequest($request->reveal()); - static::assertSame( + self::assertSame( 10, $result->getPageUid() ); @@ -237,13 +239,13 @@ class FactoryTest extends TestCase 'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', ]); - static::assertInstanceOf(Pageview::class, $result); - static::assertSame(1, $result->getUid()); - static::assertSame(2, $result->getPageUid()); - static::assertSame($siteLanguage->reveal(), $result->getLanguage()); - static::assertSame('1533906435', $result->getCrdate()->format('U')); - static::assertSame(0, $result->getPageType()); - static::assertSame('https://example.com/path', $result->getUrl()); - static::assertSame('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', $result->getUserAgent()); + self::assertInstanceOf(Pageview::class, $result); + self::assertSame(1, $result->getUid()); + self::assertSame(2, $result->getPageUid()); + self::assertSame($siteLanguage->reveal(), $result->getLanguage()); + self::assertSame('1533906435', $result->getCrdate()->format('U')); + self::assertSame(0, $result->getPageType()); + self::assertSame('https://example.com/path', $result->getUrl()); + self::assertSame('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', $result->getUserAgent()); } } diff --git a/Tests/Unit/Domain/Repository/PageviewTest.php b/Tests/Unit/Domain/Repository/PageviewTest.php deleted file mode 100644 index 7b4f844..0000000 --- a/Tests/Unit/Domain/Repository/PageviewTest.php +++ /dev/null @@ -1,231 +0,0 @@ - - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -use DanielSiepmann\Tracking\Domain\Model\Pageview as Model; -use DanielSiepmann\Tracking\Domain\Pageview\Factory; -use DanielSiepmann\Tracking\Domain\Repository\Pageview; -use Doctrine\DBAL\Statement; -use Prophecy\PhpUnit\ProphecyTrait; -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Database\Query\QueryBuilder; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; - -/** - * @covers DanielSiepmann\Tracking\Domain\Repository\Pageview - */ -class PageviewTest extends TestCase -{ - use ProphecyTrait; - - /** - * @test - */ - public function modelCanBeAdded(): void - { - $connection = $this->prophesize(Connection::class); - $factory = $this->prophesize(Factory::class); - - $dateTime = $this->prophesize(\DateTimeImmutable::class); - $dateTime->format('U')->willReturn(1582660189); - - $language = $this->prophesize(SiteLanguage::class); - $language->getLanguageId()->willReturn(2); - - $model = $this->prophesize(Model::class); - $model->getPageUid()->willReturn(10); - $model->getCrdate()->willReturn($dateTime->reveal()); - $model->getPageType()->willReturn(999); - $model->getLanguage()->willReturn($language->reveal()); - $model->getUrl()->willReturn('https://example.com/path.html'); - $model->getUserAgent()->willReturn('Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0'); - $model->getOperatingSystem()->willReturn('Linux'); - - $connection->insert( - 'tx_tracking_pageview', - [ - 'pid' => 10, - 'crdate' => 1582660189, - 'tstamp' => 1582660189, - 'type' => 999, - 'sys_language_uid' => 2, - 'url' => 'https://example.com/path.html', - 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0', - 'operating_system' => 'Linux', - ] - )->willReturn(1)->shouldBeCalledTimes(1); - - $subject = new Pageview($connection->reveal(), $factory->reveal()); - $subject->add($model->reveal()); - } - - /** - * @test - */ - public function throwsExceptionIfModelToUodateHasNoUid(): void - { - $connection = $this->prophesize(Connection::class); - $factory = $this->prophesize(Factory::class); - - $model = $this->prophesize(Model::class); - $model->getUid()->willReturn(0); - - $subject = new Pageview($connection->reveal(), $factory->reveal()); - $this->expectExceptionMessage('Can not update pageview if uid is 0.'); - $subject->update($model->reveal()); - } - - /** - * @test - */ - public function modelCanBeUpdated(): void - { - $connection = $this->prophesize(Connection::class); - $factory = $this->prophesize(Factory::class); - - $dateTime = $this->prophesize(\DateTimeImmutable::class); - $dateTime->format('U')->willReturn(1582660189); - - $language = $this->prophesize(SiteLanguage::class); - $language->getLanguageId()->willReturn(2); - - $model = $this->prophesize(Model::class); - $model->getUid()->willReturn(1); - $model->getPageUid()->willReturn(10); - $model->getCrdate()->willReturn($dateTime->reveal()); - $model->getPageType()->willReturn(999); - $model->getLanguage()->willReturn($language->reveal()); - $model->getUrl()->willReturn('https://example.com/path.html'); - $model->getUserAgent()->willReturn('Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0'); - $model->getOperatingSystem()->willReturn('Linux'); - - $connection->update( - 'tx_tracking_pageview', - [ - 'pid' => 10, - 'crdate' => 1582660189, - 'tstamp' => 1582660189, - 'type' => 999, - 'sys_language_uid' => 2, - 'url' => 'https://example.com/path.html', - 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0', - 'operating_system' => 'Linux', - ], - [ - 'uid' => 1 - ] - )->willReturn(1)->shouldBeCalledTimes(1); - - $subject = new Pageview($connection->reveal(), $factory->reveal()); - $subject->update($model->reveal()); - } - - /** - * @test - */ - public function returnsACountOfAllModels(): void - { - $statement = $this->prophesize(Statement::class); - $statement->fetchColumn()->willReturn(10); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->count('uid')->willReturn($queryBuilder->reveal()); - $queryBuilder->from('tx_tracking_pageview')->willReturn($queryBuilder->reveal()); - $queryBuilder->execute()->willReturn($statement->reveal()); - - $connection = $this->prophesize(Connection::class); - $connection->createQueryBuilder()->willReturn($queryBuilder->reveal()); - - $factory = $this->prophesize(Factory::class); - - $subject = new Pageview($connection->reveal(), $factory->reveal()); - static::assertSame(10, $subject->countAll()); - } - - /** - * @test - */ - public function returnsAllModells(): void - { - $statement = $this->prophesize(Statement::class); - $statement->fetch()->willReturn( - [ - 'pid' => '10', - 'crdate' => '1595948372', - 'type' => '0', - 'sys_language_uid' => '0', - 'url' => 'https://example.com/path/file.html', - 'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', - ], - [ - 'pid' => '9', - 'crdate' => '1595948376', - 'type' => '0', - 'sys_language_uid' => '0', - 'url' => 'https://example.com/path/file.html', - 'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', - ], - false - ); - - $queryBuilder = $this->prophesize(QueryBuilder::class); - $queryBuilder->select('*')->willReturn($queryBuilder->reveal()); - $queryBuilder->from('tx_tracking_pageview')->willReturn($queryBuilder->reveal()); - $queryBuilder->execute()->willReturn($statement->reveal()); - - $connection = $this->prophesize(Connection::class); - $connection->createQueryBuilder()->willReturn($queryBuilder->reveal()); - - $model1 = $this->prophesize(Model::class); - $model1->getPageUid()->willReturn(10); - $model2 = $this->prophesize(Model::class); - $model2->getPageUid()->willReturn(9); - - $factory = $this->prophesize(Factory::class); - $factory->fromDbRow([ - 'pid' => '10', - 'crdate' => '1595948372', - 'type' => '0', - 'sys_language_uid' => '0', - 'url' => 'https://example.com/path/file.html', - 'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', - ])->willReturn($model1->reveal()); - $factory->fromDbRow([ - 'pid' => '9', - 'crdate' => '1595948376', - 'type' => '0', - 'sys_language_uid' => '0', - 'url' => 'https://example.com/path/file.html', - 'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', - ])->willReturn($model2->reveal()); - - $subject = new Pageview($connection->reveal(), $factory->reveal()); - static::assertCount(2, $subject->findAll()); - - $pageUid = 10; - foreach ($subject->findAll() as $model) { - static::assertSame($pageUid, $model->getPageUid()); - --$pageUid; - } - } -} diff --git a/Tests/Unit/Domain/Repository/RecordviewTest.php b/Tests/Unit/Domain/Repository/RecordviewTest.php deleted file mode 100644 index 2e57035..0000000 --- a/Tests/Unit/Domain/Repository/RecordviewTest.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -use DanielSiepmann\Tracking\Domain\Model\Recordview as Model; -use DanielSiepmann\Tracking\Domain\Repository\Recordview; -use Prophecy\PhpUnit\ProphecyTrait; -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase as TestCase; - -/** - * @covers DanielSiepmann\Tracking\Domain\Repository\Recordview - */ -class RecordviewTest extends TestCase -{ - use ProphecyTrait; - - /** - * @test - */ - public function modelCanBeAdded(): void - { - $connection = $this->prophesize(Connection::class); - - $dateTime = $this->prophesize(\DateTimeImmutable::class); - $dateTime->format('U')->willReturn(1582660189); - - $language = $this->prophesize(SiteLanguage::class); - $language->getLanguageId()->willReturn(2); - - $model = $this->prophesize(Model::class); - $model->getPageUid()->willReturn(10); - $model->getCrdate()->willReturn($dateTime->reveal()); - $model->getLanguage()->willReturn($language->reveal()); - $model->getUrl()->willReturn('https://example.com/path.html'); - $model->getUserAgent()->willReturn('Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0'); - $model->getOperatingSystem()->willReturn('Linux'); - $model->getRecordUid()->willReturn(10); - $model->getTableName()->willReturn('sys_category'); - - $connection->insert( - 'tx_tracking_recordview', - [ - 'pid' => 10, - 'crdate' => 1582660189, - 'tstamp' => 1582660189, - 'sys_language_uid' => 2, - 'url' => 'https://example.com/path.html', - 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0) Gecko/20100101 Firefox/74.0', - 'operating_system' => 'Linux', - 'record_uid' => 10, - 'record_table_name' => 'sys_category', - 'record' => 'sys_category_10', - ] - )->willReturn(1)->shouldBeCalledTimes(1); - - $subject = new Recordview($connection->reveal()); - $subject->add($model->reveal()); - } -} diff --git a/composer.json b/composer.json index f083a0e..1747ad7 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ "symfony/expression-language": "^5.2", "typo3/cms-backend": "^10.4 || ^11.5", "typo3/cms-core": "^10.4 || ^11.5", - "typo3/cms-dashboard": "^10.4 || ^11.5" + "typo3/cms-dashboard": "^10.4 || ^11.5", + "matomo/device-detector": "^6.0" }, "require-dev": { "phpunit/phpunit": "^9.0", diff --git a/ext_tables.sql b/ext_tables.sql index 5a57184..9b7fe41 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -1,21 +1,34 @@ CREATE TABLE tx_tracking_pageview ( url text, user_agent text, - operating_system varchar(255) DEFAULT '' NOT NULL, type int(11) unsigned DEFAULT '0' NOT NULL, + compatible_version varchar(11) DEFAULT 'v1.1.4' NOT NULL, KEY page_views_per_page (pid,uid,crdate), KEY language (l10n_parent,sys_language_uid), + KEY compatible_version (compatible_version), ); CREATE TABLE tx_tracking_recordview ( url text, user_agent text, - operating_system varchar(255) DEFAULT '' NOT NULL, record varchar(255) DEFAULT '' NOT NULL, record_uid int(11) unsigned DEFAULT '0' NOT NULL, record_table_name varchar(255) DEFAULT '' NOT NULL, + compatible_version varchar(11) DEFAULT 'v1.1.4' NOT NULL, KEY record_views_per_page (pid,uid,crdate), KEY language (l10n_parent,sys_language_uid), + KEY compatible_version (compatible_version), +); + +CREATE TABLE tx_tracking_tag ( + record_uid int(11) unsigned DEFAULT '0' NOT NULL, + record_table_name varchar(255) DEFAULT '' NOT NULL, + name varchar(255) DEFAULT '' NOT NULL, + value longtext DEFAULT '' NOT NULL, + compatible_version varchar(11) DEFAULT 'v2.0.0' NOT NULL, + + KEY combined_identifier (record_uid,record_table_name,name,value), + KEY compatible_version (compatible_version), );