Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Application/Kernel/PluginList.php1
-rw-r--r--core/DataAccess/LogQueryBuilder/JoinGenerator.php46
-rw-r--r--core/DataAccess/LogQueryBuilder/JoinTables.php135
-rw-r--r--plugins/ExampleLogTables/Columns/GroupAttributeAdmin.php14
-rw-r--r--plugins/ExampleLogTables/Columns/UserAttributeGender.php14
-rw-r--r--plugins/ExampleLogTables/Dao/CustomGroupLog.php66
-rw-r--r--plugins/ExampleLogTables/Dao/CustomUserLog.php68
-rw-r--r--plugins/ExampleLogTables/ExampleLogTables.php26
-rw-r--r--plugins/ExampleLogTables/Tracker/LogTable/CustomGroupLog.php34
-rw-r--r--plugins/ExampleLogTables/Tracker/LogTable/CustomUserLog.php34
-rw-r--r--plugins/ExampleLogTables/plugin.json29
-rw-r--r--plugins/ExampleLogTables/tests/Fixtures/VisitsWithUserIdAndCustomData.php110
-rw-r--r--plugins/ExampleLogTables/tests/System/CustomLogTablesTest.php138
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__Actions.get_month.xml11
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__UserId.getUsers_month.xml27
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__VisitsSummary.get_month.xml14
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__Actions.get_month.xml11
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__UserId.getUsers_month.xml51
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__VisitsSummary.get_month.xml14
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__Actions.get_month.xml11
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__UserId.getUsers_month.xml27
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__VisitsSummary.get_month.xml14
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__Actions.get_month.xml11
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__UserId.getUsers_month.xml27
-rw-r--r--plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__VisitsSummary.get_month.xml14
-rw-r--r--plugins/UserId/Archiver.php2
-rw-r--r--tests/PHPUnit/Framework/Mock/Plugin/CustomUserLogTable.php28
-rw-r--r--tests/PHPUnit/Framework/Mock/Plugin/LogTablesProvider.php4
-rw-r--r--tests/PHPUnit/Framework/Mock/Plugin/OtherCustomUserLogTable.php28
-rw-r--r--tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinGeneratorTest.php43
-rw-r--r--tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinTablesTest.php14
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png4
33 files changed, 1029 insertions, 45 deletions
diff --git a/core/Application/Kernel/PluginList.php b/core/Application/Kernel/PluginList.php
index c960b9fd89..2a79d9a8e3 100644
--- a/core/Application/Kernel/PluginList.php
+++ b/core/Application/Kernel/PluginList.php
@@ -39,6 +39,7 @@ class PluginList
'ExampleVisualization',
'ExamplePluginTemplate',
'ExampleTracker',
+ 'ExampleLogTables',
'ExampleReport',
'MobileAppMeasurable',
'Provider',
diff --git a/core/DataAccess/LogQueryBuilder/JoinGenerator.php b/core/DataAccess/LogQueryBuilder/JoinGenerator.php
index 506ee5e9d6..f964ed6594 100644
--- a/core/DataAccess/LogQueryBuilder/JoinGenerator.php
+++ b/core/DataAccess/LogQueryBuilder/JoinGenerator.php
@@ -53,6 +53,19 @@ class JoinGenerator
if (!$logTable->getColumnToJoinOnIdVisit()) {
$tableNameToJoin = $logTable->getLinkTableToBeAbleToJoinOnVisit();
+ if (empty($tableNameToJoin) && $logTable->getWaysToJoinToOtherLogTables()) {
+ foreach ($logTable->getWaysToJoinToOtherLogTables() as $otherLogTable => $column) {
+ if ($this->tables->hasJoinedTable($otherLogTable)) {
+ $this->tables->addTableDependency($table, $otherLogTable);
+ continue;
+ }
+ if ($this->tables->isTableJoinableOnVisit($otherLogTable) || $this->tables->isTableJoinableOnAction($otherLogTable)) {
+ $this->addMissingTablesForOtherTableJoin($otherLogTable, $table);
+ }
+ }
+ continue;
+ }
+
if ($index > 0 && !$this->tables->hasJoinedTable($tableNameToJoin)) {
$this->tables->addTableToJoin($tableNameToJoin);
}
@@ -96,6 +109,30 @@ class JoinGenerator
}
}
+ private function addMissingTablesForOtherTableJoin($tableName, $dependentTable)
+ {
+ $this->tables->addTableDependency($dependentTable, $tableName);
+
+ if ($this->tables->hasJoinedTable($tableName)) {
+ return;
+ }
+
+ $table = $this->tables->getLogTable($tableName);
+
+ if ($table->getColumnToJoinOnIdAction() || $table->getColumnToJoinOnIdAction() || $table->getLinkTableToBeAbleToJoinOnVisit()) {
+ $this->tables->addTableToJoin($tableName);
+ return;
+ }
+
+ $otherTableJoins = $table->getWaysToJoinToOtherLogTables();
+
+ foreach ($otherTableJoins as $logTable => $column) {
+ $this->addMissingTablesForOtherTableJoin($logTable, $tableName);
+ }
+
+ $this->tables->addTableToJoin($tableName);
+ }
+
/**
* Generate the join sql based on the needed tables
* @throws Exception if tables can't be joined
@@ -206,6 +243,15 @@ class JoinGenerator
break;
}
+
+ $otherJoins = $logTable->getWaysToJoinToOtherLogTables();
+ foreach ($otherJoins as $joinTable => $column) {
+ if($availableLogTable->getName() == $joinTable) {
+ $join = sprintf("`%s`.`%s` = `%s`.`%s`", $table, $column, $availableLogTable->getName(), $column);
+ break;
+ }
+ }
+
}
if (!isset($join)) {
diff --git a/core/DataAccess/LogQueryBuilder/JoinTables.php b/core/DataAccess/LogQueryBuilder/JoinTables.php
index 70d4b75610..cf06382904 100644
--- a/core/DataAccess/LogQueryBuilder/JoinTables.php
+++ b/core/DataAccess/LogQueryBuilder/JoinTables.php
@@ -19,6 +19,40 @@ class JoinTables extends \ArrayObject
*/
private $logTableProvider;
+ // NOTE: joins can be specified explicitly as arrays w/ 'joinOn' keys or implicitly as table names. when
+ // table names are used, the joins dependencies are assumed based on how we want to order those joins.
+ // the below table list the possible dependencies of each table, and is specifically designed to enforce
+ // the following order:
+ // log_link_visit_action, log_action, log_visit, log_conversion, log_conversion_item
+ // which means if an array is supplied where log_visit comes before log_link_visitAction, it will
+ // be moved to after it.
+ private $implicitTableDependencies = [
+ 'log_link_visit_action' => [
+ // empty
+ ],
+ 'log_action' => [
+ 'log_link_visit_action',
+ 'log_conversion',
+ 'log_conversion_item',
+ 'log_visit',
+ ],
+ 'log_visit' => [
+ 'log_link_visit_action',
+ 'log_action',
+ ],
+ 'log_conversion' => [
+ 'log_link_visit_action',
+ 'log_action',
+ 'log_visit',
+ ],
+ 'log_conversion_item' => [
+ 'log_link_visit_action',
+ 'log_action',
+ 'log_visit',
+ 'log_conversion',
+ ],
+ ];
+
/**
* Tables constructor.
* @param LogTablesProvider $logTablesProvider
@@ -125,6 +159,73 @@ class JoinTables extends \ArrayObject
$this->exchangeArray($sorted);
}
+ public function isTableJoinableOnVisit($tableToCheck)
+ {
+ $table = $this->getLogTable($tableToCheck);
+
+ if (empty($table)) {
+ return false;
+ }
+
+ if ($table->getColumnToJoinOnIdVisit()) {
+ return true;
+ }
+
+ if ($table->getLinkTableToBeAbleToJoinOnVisit()) {
+ return true;
+ }
+
+ $otherWays = $table->getWaysToJoinToOtherLogTables();
+
+ if (empty($otherWays)) {
+ return false;
+ }
+
+ foreach ($otherWays as $logTable => $column) {
+ if ($logTable == 'log_visit' || $this->isTableJoinableOnVisit($logTable)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function isTableJoinableOnAction($tableToCheck)
+ {
+ $table = $this->getLogTable($tableToCheck);
+
+ if (empty($table)) {
+ return false;
+ }
+
+ if ($table->getColumnToJoinOnIdAction()) {
+ return true;
+ }
+
+ $otherWays = $table->getWaysToJoinToOtherLogTables();
+
+ if (empty($otherWays)) {
+ return false;
+ }
+
+ foreach ($otherWays as $logTable => $column) {
+ if ($logTable == 'log_action' || $this->isTableJoinableOnAction($logTable)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function addTableDependency($table, $dependentTable)
+ {
+ if (!empty($this->implicitTableDependencies[$table])) {
+ return;
+ }
+
+ $this->implicitTableDependencies[$table] = [$dependentTable];
+ }
+
private function checkTableCanBeUsedForSegmentation($tableName)
{
if (!is_array($tableName) && !$this->getLogTable($tableName)) {
@@ -154,39 +255,7 @@ class JoinTables extends \ArrayObject
private function assumeImplicitJoinDependencies($allTablesToQuery, $table)
{
- // NOTE: joins can be specified explicitly as arrays w/ 'joinOn' keys or implicitly as table names. when
- // table names are used, the joins dependencies are assumed based on how we want to order those joins.
- // the below table list the possible dependencies of each table, and is specifically designed to enforce
- // the following order:
- // log_link_visit_action, log_action, log_visit, log_conversion, log_conversion_item
- // which means if an array is supplied where log_visit comes before log_link_visitAction, it will
- // be moved to after it.
- $implicitTableDependencies = [
- 'log_link_visit_action' => [
- // empty
- ],
- 'log_action' => [
- 'log_link_visit_action',
- 'log_conversion',
- 'log_conversion_item',
- 'log_visit',
- ],
- 'log_visit' => [
- 'log_link_visit_action',
- 'log_action',
- ],
- 'log_conversion' => [
- 'log_link_visit_action',
- 'log_action',
- 'log_visit',
- ],
- 'log_conversion_item' => [
- 'log_link_visit_action',
- 'log_action',
- 'log_visit',
- 'log_conversion',
- ],
- ];
+ $implicitTableDependencies = $this->implicitTableDependencies;
$result = [];
if (isset($implicitTableDependencies[$table])) {
diff --git a/plugins/ExampleLogTables/Columns/GroupAttributeAdmin.php b/plugins/ExampleLogTables/Columns/GroupAttributeAdmin.php
new file mode 100644
index 0000000000..3c11627058
--- /dev/null
+++ b/plugins/ExampleLogTables/Columns/GroupAttributeAdmin.php
@@ -0,0 +1,14 @@
+<?php
+namespace Piwik\Plugins\ExampleLogTables\Columns;
+
+use Piwik\Columns\Dimension;
+
+class GroupAttributeAdmin extends Dimension
+{
+ protected $dbTableName = 'log_group';
+ protected $category = 'General_Visitors';
+ protected $type = self::TYPE_BOOL;
+ protected $columnName = 'is_admin';
+ protected $segmentName = 'isadmin';
+ protected $nameSingular = 'Admin privileges';
+}
diff --git a/plugins/ExampleLogTables/Columns/UserAttributeGender.php b/plugins/ExampleLogTables/Columns/UserAttributeGender.php
new file mode 100644
index 0000000000..4a5ef0ab2c
--- /dev/null
+++ b/plugins/ExampleLogTables/Columns/UserAttributeGender.php
@@ -0,0 +1,14 @@
+<?php
+namespace Piwik\Plugins\ExampleLogTables\Columns;
+
+use Piwik\Columns\Dimension;
+
+class UserAttributeGender extends Dimension
+{
+ protected $dbTableName = 'log_custom';
+ protected $category = 'General_Visitors';
+ protected $type = self::TYPE_TEXT;
+ protected $columnName = 'gender';
+ protected $segmentName = 'attrgender';
+ protected $nameSingular = 'Gender';
+}
diff --git a/plugins/ExampleLogTables/Dao/CustomGroupLog.php b/plugins/ExampleLogTables/Dao/CustomGroupLog.php
new file mode 100644
index 0000000000..2b71ff33e6
--- /dev/null
+++ b/plugins/ExampleLogTables/Dao/CustomGroupLog.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleLogTables\Dao;
+
+use Piwik\Common;
+use Piwik\Db;
+use Piwik\DbHelper;
+
+class CustomGroupLog
+{
+ private $table = 'log_group';
+ private $tablePrefixed = '';
+
+ public function __construct()
+ {
+ $this->tablePrefixed = Common::prefixTable($this->table);
+ }
+
+ public function install()
+ {
+ DbHelper::createTable($this->table, "
+ `group` VARCHAR(30) NOT NULL,
+ `is_admin` TINYINT(1) NOT NULL,
+ PRIMARY KEY (`group`)");
+ }
+
+ public function uninstall()
+ {
+ Db::query(sprintf('DROP TABLE IF EXISTS `%s`', $this->tablePrefixed));
+ }
+
+ private function getDb()
+ {
+ return Db::get();
+ }
+
+ public function getAllRecords()
+ {
+ return $this->getDb()->fetchAll('SELECT * FROM ' . $this->tablePrefixed);
+ }
+
+ public function addGroupInformation($group, $isAdmin)
+ {
+ $columns = array(
+ 'group' => $group,
+ 'is_admin' => $isAdmin
+ );
+
+ $bind = array_values($columns);
+ $placeholder = Common::getSqlStringFieldsArray($columns);
+
+ $sql = sprintf('INSERT INTO %s (`%s`) VALUES(%s)',
+ $this->tablePrefixed, implode('`,`', array_keys($columns)), $placeholder);
+
+ $db = $this->getDb();
+
+ $db->query($sql, $bind);
+ }
+}
+
diff --git a/plugins/ExampleLogTables/Dao/CustomUserLog.php b/plugins/ExampleLogTables/Dao/CustomUserLog.php
new file mode 100644
index 0000000000..50f3016301
--- /dev/null
+++ b/plugins/ExampleLogTables/Dao/CustomUserLog.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleLogTables\Dao;
+
+use Piwik\Common;
+use Piwik\Db;
+use Piwik\DbHelper;
+
+class CustomUserLog
+{
+ private $table = 'log_custom';
+ private $tablePrefixed = '';
+
+ public function __construct()
+ {
+ $this->tablePrefixed = Common::prefixTable($this->table);
+ }
+
+ public function install()
+ {
+ DbHelper::createTable($this->table, "
+ `user_id` VARCHAR(200) NOT NULL,
+ `gender` VARCHAR(30) NOT NULL,
+ `group` VARCHAR(30) NOT NULL,
+ PRIMARY KEY (user_id)");
+ }
+
+ public function uninstall()
+ {
+ Db::query(sprintf('DROP TABLE IF EXISTS `%s`', $this->tablePrefixed));
+ }
+
+ private function getDb()
+ {
+ return Db::get();
+ }
+
+ public function getAllRecords()
+ {
+ return $this->getDb()->fetchAll('SELECT * FROM ' . $this->tablePrefixed);
+ }
+
+ public function addUserInformation($userId, $group, $gender)
+ {
+ $columns = array(
+ 'user_id' => $userId,
+ 'group' => $group,
+ 'gender' => $gender
+ );
+
+ $bind = array_values($columns);
+ $placeholder = Common::getSqlStringFieldsArray($columns);
+
+ $sql = sprintf('INSERT INTO %s (`%s`) VALUES(%s)',
+ $this->tablePrefixed, implode('`,`', array_keys($columns)), $placeholder);
+
+ $db = $this->getDb();
+
+ $db->query($sql, $bind);
+ }
+}
+
diff --git a/plugins/ExampleLogTables/ExampleLogTables.php b/plugins/ExampleLogTables/ExampleLogTables.php
new file mode 100644
index 0000000000..caf83d594b
--- /dev/null
+++ b/plugins/ExampleLogTables/ExampleLogTables.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleLogTables;
+
+use Piwik\Plugins\ExampleLogTables\Dao\CustomUserLog;
+use Piwik\Plugins\ExampleLogTables\Dao\CustomGroupLog;
+
+class ExampleLogTables extends \Piwik\Plugin
+{
+ public function install()
+ {
+ // Install custom log table [disabled as example only]
+
+ // $userLog = new CustomUserLog();
+ // $userLog->install();
+
+ // $userLog = new CustomGroupLog();
+ // $userLog->install();
+ }
+} \ No newline at end of file
diff --git a/plugins/ExampleLogTables/Tracker/LogTable/CustomGroupLog.php b/plugins/ExampleLogTables/Tracker/LogTable/CustomGroupLog.php
new file mode 100644
index 0000000000..7ee199bc11
--- /dev/null
+++ b/plugins/ExampleLogTables/Tracker/LogTable/CustomGroupLog.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleLogTables\Tracker\LogTable;
+
+use Piwik\Tracker\LogTable;
+
+class CustomGroupLog extends LogTable
+{
+ public function getName()
+ {
+ return 'log_group';
+ }
+
+ public function getIdColumn()
+ {
+ return 'group';
+ }
+
+ public function getPrimaryKey()
+ {
+ return ['group'];
+ }
+
+ public function getWaysToJoinToOtherLogTables()
+ {
+ return ['log_custom' => 'group'];
+ }
+}
diff --git a/plugins/ExampleLogTables/Tracker/LogTable/CustomUserLog.php b/plugins/ExampleLogTables/Tracker/LogTable/CustomUserLog.php
new file mode 100644
index 0000000000..5cbc20d83a
--- /dev/null
+++ b/plugins/ExampleLogTables/Tracker/LogTable/CustomUserLog.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\ExampleLogTables\Tracker\LogTable;
+
+use Piwik\Tracker\LogTable;
+
+class CustomUserLog extends LogTable
+{
+ public function getName()
+ {
+ return 'log_custom';
+ }
+
+ public function getIdColumn()
+ {
+ return 'user_id';
+ }
+
+ public function getPrimaryKey()
+ {
+ return ['user_id'];
+ }
+
+ public function getWaysToJoinToOtherLogTables()
+ {
+ return ['log_visit' => 'user_id'];
+ }
+}
diff --git a/plugins/ExampleLogTables/plugin.json b/plugins/ExampleLogTables/plugin.json
new file mode 100644
index 0000000000..3e6442de06
--- /dev/null
+++ b/plugins/ExampleLogTables/plugin.json
@@ -0,0 +1,29 @@
+{
+ "name": "ExampleLogTables",
+ "description": "Matomo Platform showcase: how to create custom log tables.",
+ "version": "0.1.0",
+ "theme": false,
+ "require": {
+ "piwik": ">=3.0.0-b1,<4.0.0-b1"
+ },
+ "authors": [
+ {
+ "name": "Matomo",
+ "email": "",
+ "homepage": ""
+ }
+ ],
+ "support": {
+ "email": "",
+ "issues": "",
+ "forum": "",
+ "irc": "",
+ "wiki": "",
+ "source": "",
+ "docs": "",
+ "rss": ""
+ },
+ "homepage": "",
+ "license": "GPL v3+",
+ "keywords": []
+}
diff --git a/plugins/ExampleLogTables/tests/Fixtures/VisitsWithUserIdAndCustomData.php b/plugins/ExampleLogTables/tests/Fixtures/VisitsWithUserIdAndCustomData.php
new file mode 100644
index 0000000000..4324e58d54
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/Fixtures/VisitsWithUserIdAndCustomData.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\ExampleLogTables\tests\Fixtures;
+
+use Piwik\Date;
+use Piwik\Plugins\ExampleLogTables\Dao\CustomGroupLog;
+use Piwik\Plugins\ExampleLogTables\Dao\CustomUserLog;
+use Piwik\Tests\Framework\Fixture;
+
+class VisitsWithUserIdAndCustomData extends Fixture
+{
+ public $dateTime = '2018-02-01 11:22:33';
+ public $idSite = 1;
+
+ private static $countryCodes = ['CA', 'CN', 'DE', 'ES', 'FR', 'IE', 'IN', 'IT', 'MX', 'PT', 'RU', 'GB', 'US'];
+
+ public function setUp()
+ {
+ if (!self::siteCreated($idSite = 1)) {
+ self::createWebsite($this->dateTime);
+ }
+
+ // set up database tables
+ $userLog = new CustomUserLog();
+ $userLog->install();
+ $groupLog = new CustomGroupLog();
+ $groupLog->install();
+
+ $this->trackVisits();
+ $this->insertCustomUserLogData();
+ $this->insertCustomGroupLogData();
+ }
+
+ private function trackVisits()
+ {
+ $t = self::getTracker($this->idSite, $this->dateTime, $defaultInit = true);
+ $t->setTokenAuth(self::getTokenAuth());
+ $t->enableBulkTracking();
+
+ foreach (array('user1', 'user2', 'user3', 'user4', false) as $key => $userId) {
+ for ($numVisits = 0; $numVisits < ($key+1) * 10; $numVisits++) {
+ $t->setUserId($userId);
+ $t->setPlugins($numVisits % 3 == 0, $numVisits % 5 == 0, $numVisits % 7 == 0);
+ $t->setBrowserHasCookies($numVisits % 3 == 0);
+ $t->setCountry(self::$countryCodes[$numVisits % count(self::$countryCodes)]);
+
+ if ($numVisits % 5 == 0) {
+ $t->doTrackSiteSearch('some search term' . $numVisits);
+ }
+
+ if ($numVisits % 4 == 0) {
+ $t->doTrackEvent('Event action ' . $numVisits, 'event cat ' . $numVisits);
+ }
+
+ if ($numVisits % 7 == 0) {
+ $t->doTrackContentInteraction('click', 'slider ' . $numVisits%4);
+ }
+
+ if ($numVisits % 7 == 4) {
+ $t->doTrackAction('http://out.link', 'outlink');
+ }
+
+ if ($numVisits % 5 == 3) {
+ $t->setEcommerceView('SKU VERY nice indeed ' . ($numVisits%3), 'PRODUCT name ' . ($numVisits%4), 'category ' . ($numVisits%5), $numVisits*2.79);
+ }
+
+ $t->setForceNewVisit();
+ $t->setUrl('http://example.org/my/dir/page' . ($numVisits % 4));
+
+ $visitDateTime = Date::factory($this->dateTime)->addHour($numVisits*6)->getDatetime();
+ $t->setForceVisitDateTime($visitDateTime);
+
+ if ($numVisits % 7 == 0) {
+ $t->doTrackAction('http://example.org/download.pdf', 'download');
+ }
+
+ self::assertTrue($t->doTrackPageView('incredible title ' . ($numVisits % 3)));
+
+ if ($numVisits % 9 == 0) {
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour($numVisits*6.1)->getDatetime());
+ $t->addEcommerceItem('SKU VERY nice indeed ' . ($numVisits%3), 'PRODUCT name ' . ($numVisits%4), 'category ' . ($numVisits%5), $numVisits*2.79);
+ self::assertTrue($t->doTrackEcommerceCartUpdate($numVisits*17));
+ }
+ }
+ }
+
+ self::checkBulkTrackingResponse($t->doBulkTrack());
+ }
+
+ private function insertCustomUserLogData()
+ {
+ $customLog = new CustomUserLog();
+ $customLog->addUserInformation('user1', 'admin', 'men');
+ $customLog->addUserInformation('user2', 'user', 'women');
+ $customLog->addUserInformation('user3', 'admin', 'women');
+ $customLog->addUserInformation('user4', '', 'men');
+ }
+
+ private function insertCustomGroupLogData()
+ {
+ $customGroup = new CustomGroupLog();
+ $customGroup->addGroupInformation('admin', 1);
+ $customGroup->addGroupInformation('user', 0);
+ }
+} \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/CustomLogTablesTest.php b/plugins/ExampleLogTables/tests/System/CustomLogTablesTest.php
new file mode 100644
index 0000000000..1cf254f3dc
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/CustomLogTablesTest.php
@@ -0,0 +1,138 @@
+<?php
+namespace Piwik\Plugins\ExampleLogTables\tests\System;
+
+use Piwik\Plugins\ExampleLogTables\tests\Fixtures\VisitsWithUserIdAndCustomData;
+use Piwik\Tests\Framework\TestCase\SystemTestCase;
+use Piwik\Tests\Framework\TestRequest\ApiTestConfig;
+use Piwik\Tests\Framework\TestRequest\Response;
+
+/**
+ * Testing Custom Log Tables
+ *
+ * @group ExampleLogTables
+ * @group Plugins
+ */
+class CustomLogTablesTest extends SystemTestCase
+{
+ /**
+ * @var VisitsWithUserIdAndCustomData
+ */
+ public static $fixture = null; // initialized below class definition
+
+ /**
+ * @dataProvider getApiForTesting
+ */
+ public function testApi($api, $params)
+ {
+ $this->runApiTests($api, $params);
+ }
+
+ /**
+ * @dataProvider getSegmentsToTest
+ */
+ public function testNoApiReturnsError($segment)
+ {
+ $dateTime = self::$fixture->dateTime;
+ $idSite1 = self::$fixture->idSite;
+
+ $params = [
+ 'idSite' => $idSite1,
+ 'date' => $dateTime,
+ 'periods' => 'month',
+ 'setDateLastN' => false,
+ 'format' => 'JSON',
+ 'segment' => $segment,
+ 'testSuffix' => ''
+ ];
+
+ $testConfig = new ApiTestConfig($params);
+ $testRequests = $this->getTestRequestsCollection('all', $testConfig, 'all');
+
+ foreach ($testRequests->getRequestUrls() as $apiId => $requestUrl) {
+ $response = Response::loadFromApi($params, $requestUrl, false);
+ $decoded = json_decode($response->getResponseText(), true);
+
+ if (is_array($decoded) && isset($decoded['result']) && $decoded['result'] == 'error') {
+ $this->fail('API returned an error when requesting ' . http_build_query($requestUrl) . "\nMessage: " . $decoded['message']);
+ }
+ }
+ }
+
+ public function getSegmentsToTest()
+ {
+ return [
+ ['attrgender==men'],
+ ['isadmin==1'],
+ ];
+ }
+
+ public function getApiForTesting()
+ {
+ $dateTime = self::$fixture->dateTime;
+ $idSite1 = self::$fixture->idSite;
+
+ $result = [
+ [[
+ 'Actions.get',
+ 'UserId.getUsers',
+ 'VisitsSummary.get'
+ ], [
+ 'idSite' => $idSite1,
+ 'date' => $dateTime,
+ 'periods' => 'month',
+ 'setDateLastN' => false,
+ 'segment' => 'attrgender==men',
+ 'testSuffix' => '_men']
+ ],
+ [[
+ 'Actions.get',
+ 'UserId.getUsers',
+ 'VisitsSummary.get'
+ ], [
+ 'idSite' => $idSite1,
+ 'date' => $dateTime,
+ 'periods' => 'month',
+ 'setDateLastN' => false,
+ 'segment' => 'attrgender==women',
+ 'testSuffix' => '_women']
+ ],
+ [[
+ 'Actions.get',
+ 'UserId.getUsers',
+ 'VisitsSummary.get'
+ ], [
+ 'idSite' => $idSite1,
+ 'date' => $dateTime,
+ 'periods' => 'month',
+ 'setDateLastN' => false,
+ 'segment' => 'isadmin==1',
+ 'testSuffix' => '_admin']
+ ],
+ [[
+ 'Actions.get',
+ 'UserId.getUsers',
+ 'VisitsSummary.get'
+ ], [
+ 'idSite' => $idSite1,
+ 'date' => $dateTime,
+ 'periods' => 'month',
+ 'setDateLastN' => false,
+ 'testSuffix' => '_all']
+ ],
+ ];
+
+ return $result;
+ }
+
+ public static function getOutputPrefix()
+ {
+ return 'ExampleLogTables';
+ }
+
+ public static function getPathToTestDirectory()
+ {
+ return dirname(__FILE__);
+ }
+}
+
+CustomLogTablesTest::$fixture = new VisitsWithUserIdAndCustomData();
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__Actions.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__Actions.get_month.xml
new file mode 100644
index 0000000000..d73153a828
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__Actions.get_month.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_pageviews>45</nb_pageviews>
+ <nb_uniq_pageviews>40</nb_uniq_pageviews>
+ <nb_downloads>7</nb_downloads>
+ <nb_uniq_downloads>7</nb_uniq_downloads>
+ <nb_outlinks>0</nb_outlinks>
+ <nb_uniq_outlinks>0</nb_uniq_outlinks>
+ <nb_searches>8</nb_searches>
+ <nb_keywords>6</nb_keywords>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__UserId.getUsers_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__UserId.getUsers_month.xml
new file mode 100644
index 0000000000..e9d5ed7b27
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__UserId.getUsers_month.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>user3</label>
+ <nb_visits>34</nb_visits>
+ <nb_actions>53</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>20</sum_visit_length>
+ <bounce_count>19</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>8</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>8</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user1</label>
+ <nb_visits>12</nb_visits>
+ <nb_actions>18</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>6</sum_visit_length>
+ <bounce_count>7</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>3</sum_daily_nb_users>
+
+ </row>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__VisitsSummary.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__VisitsSummary.get_month.xml
new file mode 100644
index 0000000000..eeeb691530
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_admin__VisitsSummary.get_month.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_users>2</nb_users>
+ <nb_visits>46</nb_visits>
+ <nb_actions>71</nb_actions>
+ <nb_visits_converted>0</nb_visits_converted>
+ <bounce_count>26</bounce_count>
+ <sum_visit_length>26</sum_visit_length>
+ <max_actions>3</max_actions>
+ <bounce_rate>57%</bounce_rate>
+ <nb_actions_per_visit>1.5</nb_actions_per_visit>
+ <avg_time_on_site>1</avg_time_on_site>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__Actions.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__Actions.get_month.xml
new file mode 100644
index 0000000000..951eb7a039
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__Actions.get_month.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_pageviews>171</nb_pageviews>
+ <nb_uniq_pageviews>156</nb_uniq_pageviews>
+ <nb_downloads>24</nb_downloads>
+ <nb_uniq_downloads>24</nb_uniq_downloads>
+ <nb_outlinks>0</nb_outlinks>
+ <nb_uniq_outlinks>0</nb_uniq_outlinks>
+ <nb_searches>30</nb_searches>
+ <nb_keywords>10</nb_keywords>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__UserId.getUsers_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__UserId.getUsers_month.xml
new file mode 100644
index 0000000000..537029b08e
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__UserId.getUsers_month.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>user4</label>
+ <nb_visits>45</nb_visits>
+ <nb_actions>70</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>25</sum_visit_length>
+ <bounce_count>25</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>11</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>11</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user3</label>
+ <nb_visits>34</nb_visits>
+ <nb_actions>53</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>20</sum_visit_length>
+ <bounce_count>19</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>8</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>8</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user2</label>
+ <nb_visits>22</nb_visits>
+ <nb_actions>35</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>12</sum_visit_length>
+ <bounce_count>12</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>6</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>6</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user1</label>
+ <nb_visits>12</nb_visits>
+ <nb_actions>18</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>6</sum_visit_length>
+ <bounce_count>7</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>3</sum_daily_nb_users>
+
+ </row>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__VisitsSummary.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__VisitsSummary.get_month.xml
new file mode 100644
index 0000000000..f22cfae43b
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_all__VisitsSummary.get_month.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_uniq_visitors>54</nb_uniq_visitors>
+ <nb_users>4</nb_users>
+ <nb_visits>195</nb_visits>
+ <nb_actions>264</nb_actions>
+ <nb_visits_converted>0</nb_visits_converted>
+ <bounce_count>130</bounce_count>
+ <sum_visit_length>80</sum_visit_length>
+ <max_actions>3</max_actions>
+ <bounce_rate>67%</bounce_rate>
+ <nb_actions_per_visit>1.4</nb_actions_per_visit>
+ <avg_time_on_site>0</avg_time_on_site>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__Actions.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__Actions.get_month.xml
new file mode 100644
index 0000000000..052c729dda
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__Actions.get_month.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_pageviews>57</nb_pageviews>
+ <nb_uniq_pageviews>50</nb_uniq_pageviews>
+ <nb_downloads>8</nb_downloads>
+ <nb_uniq_downloads>8</nb_uniq_downloads>
+ <nb_outlinks>0</nb_outlinks>
+ <nb_uniq_outlinks>0</nb_uniq_outlinks>
+ <nb_searches>10</nb_searches>
+ <nb_keywords>8</nb_keywords>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__UserId.getUsers_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__UserId.getUsers_month.xml
new file mode 100644
index 0000000000..f88f48454a
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__UserId.getUsers_month.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>user4</label>
+ <nb_visits>45</nb_visits>
+ <nb_actions>70</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>25</sum_visit_length>
+ <bounce_count>25</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>11</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>11</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user1</label>
+ <nb_visits>12</nb_visits>
+ <nb_actions>18</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>6</sum_visit_length>
+ <bounce_count>7</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>3</sum_daily_nb_users>
+
+ </row>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__VisitsSummary.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__VisitsSummary.get_month.xml
new file mode 100644
index 0000000000..4e9a3bd824
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_men__VisitsSummary.get_month.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_users>2</nb_users>
+ <nb_visits>57</nb_visits>
+ <nb_actions>88</nb_actions>
+ <nb_visits_converted>0</nb_visits_converted>
+ <bounce_count>32</bounce_count>
+ <sum_visit_length>31</sum_visit_length>
+ <max_actions>3</max_actions>
+ <bounce_rate>56%</bounce_rate>
+ <nb_actions_per_visit>1.5</nb_actions_per_visit>
+ <avg_time_on_site>1</avg_time_on_site>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__Actions.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__Actions.get_month.xml
new file mode 100644
index 0000000000..4269b53424
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__Actions.get_month.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_pageviews>57</nb_pageviews>
+ <nb_uniq_pageviews>50</nb_uniq_pageviews>
+ <nb_downloads>8</nb_downloads>
+ <nb_uniq_downloads>8</nb_uniq_downloads>
+ <nb_outlinks>0</nb_outlinks>
+ <nb_uniq_outlinks>0</nb_uniq_outlinks>
+ <nb_searches>10</nb_searches>
+ <nb_keywords>6</nb_keywords>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__UserId.getUsers_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__UserId.getUsers_month.xml
new file mode 100644
index 0000000000..d9abec4587
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__UserId.getUsers_month.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>user3</label>
+ <nb_visits>34</nb_visits>
+ <nb_actions>53</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>20</sum_visit_length>
+ <bounce_count>19</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>8</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>8</sum_daily_nb_users>
+
+ </row>
+ <row>
+ <label>user2</label>
+ <nb_visits>22</nb_visits>
+ <nb_actions>35</nb_actions>
+ <max_actions>3</max_actions>
+ <sum_visit_length>12</sum_visit_length>
+ <bounce_count>12</bounce_count>
+ <nb_visits_converted>0</nb_visits_converted>
+ <sum_daily_nb_uniq_visitors>6</sum_daily_nb_uniq_visitors>
+ <sum_daily_nb_users>6</sum_daily_nb_users>
+
+ </row>
+</result> \ No newline at end of file
diff --git a/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__VisitsSummary.get_month.xml b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__VisitsSummary.get_month.xml
new file mode 100644
index 0000000000..9c82720353
--- /dev/null
+++ b/plugins/ExampleLogTables/tests/System/expected/test_ExampleLogTables_women__VisitsSummary.get_month.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_users>2</nb_users>
+ <nb_visits>56</nb_visits>
+ <nb_actions>88</nb_actions>
+ <nb_visits_converted>0</nb_visits_converted>
+ <bounce_count>31</bounce_count>
+ <sum_visit_length>32</sum_visit_length>
+ <max_actions>3</max_actions>
+ <bounce_rate>55%</bounce_rate>
+ <nb_actions_per_visit>1.6</nb_actions_per_visit>
+ <avg_time_on_site>1</avg_time_on_site>
+</result> \ No newline at end of file
diff --git a/plugins/UserId/Archiver.php b/plugins/UserId/Archiver.php
index 28c32bf3c6..584f364d3c 100644
--- a/plugins/UserId/Archiver.php
+++ b/plugins/UserId/Archiver.php
@@ -80,7 +80,7 @@ class Archiver extends \Piwik\Plugin\Archiver
/** @var \Zend_Db_Statement $query */
$query = $this->getLogAggregator()->queryVisitsByDimension(
array(self::USER_ID_FIELD),
- "$userIdFieldName IS NOT NULL AND $userIdFieldName != ''",
+ "log_visit.$userIdFieldName IS NOT NULL AND log_visit.$userIdFieldName != ''",
array("LOWER(HEX($visitorIdFieldName)) as $visitorIdFieldName")
);
diff --git a/tests/PHPUnit/Framework/Mock/Plugin/CustomUserLogTable.php b/tests/PHPUnit/Framework/Mock/Plugin/CustomUserLogTable.php
new file mode 100644
index 0000000000..e06e732d16
--- /dev/null
+++ b/tests/PHPUnit/Framework/Mock/Plugin/CustomUserLogTable.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Piwik\Tests\Framework\Mock\Plugin;
+
+use Piwik\Tracker\LogTable;
+
+class CustomUserLogTable extends LogTable
+{
+ public function getName()
+ {
+ return 'log_custom';
+ }
+
+ public function getIdColumn()
+ {
+ return 'user_id';
+ }
+
+ public function getPrimaryKey()
+ {
+ return ['user_id'];
+ }
+
+ public function getWaysToJoinToOtherLogTables()
+ {
+ return ['log_visit' => 'user_id'];
+ }
+}
diff --git a/tests/PHPUnit/Framework/Mock/Plugin/LogTablesProvider.php b/tests/PHPUnit/Framework/Mock/Plugin/LogTablesProvider.php
index c563e250cd..f4a643018a 100644
--- a/tests/PHPUnit/Framework/Mock/Plugin/LogTablesProvider.php
+++ b/tests/PHPUnit/Framework/Mock/Plugin/LogTablesProvider.php
@@ -21,7 +21,9 @@ class LogTablesProvider extends \Piwik\Plugin\LogTablesProvider
new Action(),
new LinkVisitAction(),
new ConversionItem(),
- new Conversion()
+ new Conversion(),
+ new CustomUserLogTable(),
+ new OtherCustomUserLogTable()
);
}
diff --git a/tests/PHPUnit/Framework/Mock/Plugin/OtherCustomUserLogTable.php b/tests/PHPUnit/Framework/Mock/Plugin/OtherCustomUserLogTable.php
new file mode 100644
index 0000000000..68a84855cd
--- /dev/null
+++ b/tests/PHPUnit/Framework/Mock/Plugin/OtherCustomUserLogTable.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Piwik\Tests\Framework\Mock\Plugin;
+
+use Piwik\Tracker\LogTable;
+
+class OtherCustomUserLogTable extends LogTable
+{
+ public function getName()
+ {
+ return 'log_custom_other';
+ }
+
+ public function getIdColumn()
+ {
+ return 'other_id';
+ }
+
+ public function getPrimaryKey()
+ {
+ return ['other_id'];
+ }
+
+ public function getWaysToJoinToOtherLogTables()
+ {
+ return ['log_custom' => 'other_id'];
+ }
+}
diff --git a/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinGeneratorTest.php b/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinGeneratorTest.php
index 1012e58ec3..6f77720372 100644
--- a/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinGeneratorTest.php
+++ b/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinGeneratorTest.php
@@ -67,12 +67,6 @@ class JoinGeneratorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected, $generator->getJoinString());
}
- public function test_generate_getJoinString_OnlyOneTable()
- {
- $generator = $this->generate(array('log_visit'));
- $this->assertEquals('log_visit AS log_visit', $generator->getJoinString());
- }
-
public function test_generate_getJoinString_OnlyOneActionTable()
{
$generator = $this->generate(array('log_action'));
@@ -87,6 +81,43 @@ class JoinGeneratorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expected, $generator->getJoinString());
}
+ public function test_generate_getJoinString_JoinCustomVisitTable()
+ {
+ $generator = $this->generate(array('log_visit', 'log_custom'));
+ $this->assertEquals('log_visit AS log_visit LEFT JOIN log_custom AS log_custom ON `log_custom`.`user_id` = `log_visit`.`user_id`', $generator->getJoinString());
+ }
+
+ public function test_generate_getJoinString_JoinMultipleCustomVisitTable()
+ {
+ $generator = $this->generate(array('log_visit', 'log_custom_other', 'log_custom'));
+ $this->assertEquals('log_visit AS log_visit LEFT JOIN log_custom AS log_custom ON `log_custom`.`user_id` = `log_visit`.`user_id` LEFT JOIN log_custom_other AS log_custom_other ON `log_custom_other`.`other_id` = `log_custom`.`other_id`', $generator->getJoinString());
+ }
+
+ public function test_generate_getJoinString_JoinMultipleCustomVisitTableWithMissingOne()
+ {
+ $generator = $this->generate(array('log_visit', 'log_custom_other'));
+ $this->assertEquals('log_visit AS log_visit LEFT JOIN log_custom AS log_custom ON `log_custom`.`user_id` = `log_visit`.`user_id` LEFT JOIN log_custom_other AS log_custom_other ON `log_custom_other`.`other_id` = `log_custom`.`other_id`', $generator->getJoinString());
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Table 'log_visit' can't be joined for segmentation
+ *
+ * Note: the exception reports `log_visit` and not `log_custom` as it resolves the dependencies as so resolves
+ * from `log_custom` to `log_visit` but is then not able to find a way to join `log_visit` with `log_action`
+ */
+ public function test_generate_getJoinString_CustomVisitTableCantBeJoinedWithAction()
+ {
+ $generator = $this->generate(array('log_action', 'log_custom'));
+ $generator->getJoinString();
+ }
+
+ public function test_generate_getJoinString_JoinCustomVisitTableMultiple()
+ {
+ $generator = $this->generate(array('log_visit', 'log_action', 'log_custom'));
+ $this->assertEquals('log_visit AS log_visit LEFT JOIN log_link_visit_action AS log_link_visit_action ON log_link_visit_action.idvisit = log_visit.idvisit LEFT JOIN log_action AS log_action ON log_link_visit_action.idaction_url = log_action.idaction LEFT JOIN log_custom AS log_custom ON `log_custom`.`user_id` = `log_visit`.`user_id`', $generator->getJoinString());
+ }
+
public function test_generate_getJoinString_manuallyJoinedAlready()
{
$generator = $this->generate(array(
diff --git a/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinTablesTest.php b/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinTablesTest.php
index 33f5c4cdd0..6bf7395549 100644
--- a/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinTablesTest.php
+++ b/tests/PHPUnit/Unit/DataAccess/LogQueryBuilder/JoinTablesTest.php
@@ -39,6 +39,20 @@ class JoinTablesTest extends \PHPUnit_Framework_TestCase
$this->makeTables(array('log_visit', 'log_foo_bar_baz'));
}
+ public function test_hasJoinedTable_custom()
+ {
+ $tables = $this->makeTables(array('log_visit', 'log_custom'));
+ $this->assertTrue($tables->hasJoinedTable('log_visit'));
+ $this->assertTrue($tables->hasJoinedTable('log_custom'));
+ }
+
+ public function test_hasJoinedTable_custom2()
+ {
+ $tables = $this->makeTables(array('log_visit', 'log_custom_other'));
+ $this->assertTrue($tables->hasJoinedTable('log_visit'));
+ $this->assertTrue($tables->hasJoinedTable('log_custom_other'));
+ }
+
public function test_hasJoinedTable_shouldDetectIfTableIsAlreadyAdded()
{
$this->assertTrue($this->tables->hasJoinedTable('log_visit'));
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
index 97f91fba8e..75088cdb4a 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e25803802e946ac8d73770defc818e29ef83265cad9d4692dc5d3bdeeb197013
-size 1058541
+oid sha256:3dcf01d06e413501b56bd58e24738864406092435974b3dac45650d46dee4dfa
+size 1068670
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
index 8371292920..fe3156ddae 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_admin_plugins_no_internet.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:62a82dd8080ba626cb4350493e55173a5008a34b2e3036ed8631b37e70146571
-size 1059908
+oid sha256:e0869595907cda432fd31b52977c3c055df0a9969b4bd69fd9eb86b17e25e4d5
+size 1069291