File: D:/web/matomo.vdk/plugins/BotTracking/Dao/BotRequestsDao.php
<?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;
});
}
}