1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
declare(strict_types=1);
namespace Piwik\Plugins\BotTracking\Dao;
use Piwik\Common;
use Piwik\Date;
use Piwik\Db;
use Piwik\DbHelper;
class BotRequestsDao
{
public static function getTableName(): string
{
return 'log_bot_request';
}
public static function getPrefixedTableName(): string
{
return Common::prefixTable(self::getTableName());
}
/**
* Creates the log table
*/
public function createTable(): void
{
$tableName = self::getTableName();
$definition = '
`idrequest` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`idsite` INT UNSIGNED NOT NULL,
`server_time` DATETIME NOT NULL,
`created_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`idaction_url` INT UNSIGNED NULL,
`bot_name` VARCHAR(100) NOT NULL,
`bot_type` VARCHAR(50) NOT NULL,
`http_status_code` SMALLINT UNSIGNED NULL,
`response_size_bytes` INT UNSIGNED NULL,
`response_time_ms` INT UNSIGNED NULL,
`source` VARCHAR(50) NULL,
PRIMARY KEY (`idrequest`),
INDEX `index_idsite_server_time` (`idsite`, `server_time`)';
DbHelper::createTable($tableName, $definition);
}
public function dropTable(): void
{
Db::query('DROP TABLE IF EXISTS ' . self::getPrefixedTableName());
}
/**
* Insert a bot telemetry record
*
* @param array<string, scalar> $data The telemetry data to insert
* @return int The inserted record ID
*/
public function insert(array $data): int
{
$tableName = self::getPrefixedTableName();
$fields = [
'idsite',
'server_time',
'idaction_url',
'bot_name',
'bot_type',
'http_status_code',
'response_size_bytes',
'response_time_ms',
'source',
];
$values = [];
$bind = [];
foreach ($fields as $field) {
if (isset($data[$field])) {
$values[] = '?';
$bind[] = $data[$field];
} else {
$values[] = 'NULL';
}
}
$sql = sprintf(
'INSERT INTO `%s` (%s) VALUES (%s)',
$tableName,
implode(', ', $fields),
implode(', ', $values)
);
Db::query($sql, $bind);
return (int)Db::get()->lastInsertId();
}
/**
* Delete bot telemetry records older than a specified date
*
* @param Date $date Delete records older than this date
* @return int Number of deleted records
*/
public function deleteOldRecords(Date $date): int
{
$tableName = self::getPrefixedTableName();
$sql = sprintf(
'DELETE FROM `%s` WHERE server_time < ?',
$tableName
);
$result = Db::query($sql, [$date->getDatetime()]);
return (int)Db::get()->rowCount($result);
}
/**
* Delete bot telemetry records for specific sites
*
* @param array<int|string> $siteIds Delete records older than this date
* @return int Number of deleted records
*/
public function deleteRecordsForIdSites(array $siteIds): int
{
$tableName = self::getPrefixedTableName();
$siteIds = array_map('intval', $siteIds);
$sql = sprintf(
'DELETE FROM `%s` WHERE idsite IN (' . implode(', ', $siteIds) . ') LIMIT 25000',
$tableName
);
$result = Db::query($sql);
return (int)Db::get()->rowCount($result);
}
public function getLastServerTimeForSiteAndBotType(int $idSite, string $botType): ?string
{
$tableName = self::getPrefixedTableName();
return Db::fetchOne(
sprintf(
'SELECT MAX(server_time) FROM `%s` WHERE idsite = ? AND bot_type = ?',
$tableName
),
[$idSite, $botType]
);
}
/**
* @return int[]
*/
public function getDistinctIdSitesInTable(int $maxIdSite): array
{
$tableName = self::getPrefixedTableName();
$idSitesLogTable = Db::fetchAll('SELECT DISTINCT idsite FROM ' . $tableName);
$idSitesLogTable = array_column($idSitesLogTable, 'idsite');
$idSitesLogTable = array_map('intval', $idSitesLogTable);
return array_filter($idSitesLogTable, function ($idSite) use ($maxIdSite) {
return !empty($idSite) && $idSite <= $maxIdSite;
});
}
}
|