Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
249
src/Framework/Waf/Feedback/DatabaseFeedbackRepository.php
Normal file
249
src/Framework/Waf/Feedback/DatabaseFeedbackRepository.php
Normal file
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Waf\Feedback;
|
||||
|
||||
use App\Framework\Core\ValueObjects\Timestamp;
|
||||
use App\Framework\Waf\DetectionCategory;
|
||||
use App\Framework\Waf\DetectionSeverity;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Database implementation of the feedback repository
|
||||
*/
|
||||
final readonly class DatabaseFeedbackRepository implements FeedbackRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @param PDO $pdo Database connection
|
||||
*/
|
||||
public function __construct(
|
||||
private PDO $pdo
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function saveFeedback(DetectionFeedback $feedback): void
|
||||
{
|
||||
$stmt = $this->pdo->prepare('
|
||||
INSERT INTO waf_feedback (
|
||||
detection_id, feedback_type, user_id, comment,
|
||||
timestamp, category, severity, context
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
');
|
||||
|
||||
$stmt->execute([
|
||||
$feedback->detectionId,
|
||||
$feedback->feedbackType->value,
|
||||
$feedback->userId,
|
||||
$feedback->comment,
|
||||
$feedback->timestamp->toSqlString(),
|
||||
$feedback->category->value,
|
||||
$feedback->severity->value,
|
||||
json_encode($feedback->context),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFeedbackForDetection(string $detectionId): array
|
||||
{
|
||||
$stmt = $this->pdo->prepare('
|
||||
SELECT
|
||||
detection_id, feedback_type, user_id, comment,
|
||||
timestamp, category, severity, context
|
||||
FROM waf_feedback
|
||||
WHERE detection_id = ?
|
||||
ORDER BY timestamp DESC
|
||||
');
|
||||
|
||||
$stmt->execute([$detectionId]);
|
||||
|
||||
return $this->hydrateMultipleResults($stmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFeedbackByCategory(DetectionCategory $category, ?Timestamp $since = null): array
|
||||
{
|
||||
$sql = '
|
||||
SELECT
|
||||
detection_id, feedback_type, user_id, comment,
|
||||
timestamp, category, severity, context
|
||||
FROM waf_feedback
|
||||
WHERE category = ?
|
||||
';
|
||||
|
||||
$params = [$category->value];
|
||||
|
||||
if ($since !== null) {
|
||||
$sql .= ' AND timestamp >= ?';
|
||||
$params[] = $since->toSqlString();
|
||||
}
|
||||
|
||||
$sql .= ' ORDER BY timestamp DESC';
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
return $this->hydrateMultipleResults($stmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFeedbackByFeedbackType(FeedbackType $feedbackType, ?Timestamp $since = null): array
|
||||
{
|
||||
$sql = '
|
||||
SELECT
|
||||
detection_id, feedback_type, user_id, comment,
|
||||
timestamp, category, severity, context
|
||||
FROM waf_feedback
|
||||
WHERE feedback_type = ?
|
||||
';
|
||||
|
||||
$params = [$feedbackType->value];
|
||||
|
||||
if ($since !== null) {
|
||||
$sql .= ' AND timestamp >= ?';
|
||||
$params[] = $since->toSqlString();
|
||||
}
|
||||
|
||||
$sql .= ' ORDER BY timestamp DESC';
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
return $this->hydrateMultipleResults($stmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFeedbackStats(): array
|
||||
{
|
||||
// Get total count
|
||||
$totalStmt = $this->pdo->query('SELECT COUNT(*) FROM waf_feedback');
|
||||
$totalCount = (int)$totalStmt->fetchColumn();
|
||||
|
||||
// Get counts by feedback type
|
||||
$typeStmt = $this->pdo->query('
|
||||
SELECT feedback_type, COUNT(*) as count
|
||||
FROM waf_feedback
|
||||
GROUP BY feedback_type
|
||||
');
|
||||
$typeStats = [];
|
||||
while ($row = $typeStmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$typeStats[$row['feedback_type']] = (int)$row['count'];
|
||||
}
|
||||
|
||||
// Get counts by category
|
||||
$categoryStmt = $this->pdo->query('
|
||||
SELECT category, COUNT(*) as count
|
||||
FROM waf_feedback
|
||||
GROUP BY category
|
||||
');
|
||||
$categoryStats = [];
|
||||
while ($row = $categoryStmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$categoryStats[$row['category']] = (int)$row['count'];
|
||||
}
|
||||
|
||||
// Get counts by severity
|
||||
$severityStmt = $this->pdo->query('
|
||||
SELECT severity, COUNT(*) as count
|
||||
FROM waf_feedback
|
||||
GROUP BY severity
|
||||
');
|
||||
$severityStats = [];
|
||||
while ($row = $severityStmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$severityStats[$row['severity']] = (int)$row['count'];
|
||||
}
|
||||
|
||||
// Get trend data (last 30 days)
|
||||
$trendStmt = $this->pdo->query('
|
||||
SELECT
|
||||
DATE(timestamp) as date,
|
||||
feedback_type,
|
||||
COUNT(*) as count
|
||||
FROM waf_feedback
|
||||
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY)
|
||||
GROUP BY DATE(timestamp), feedback_type
|
||||
ORDER BY date
|
||||
');
|
||||
$trendData = [];
|
||||
while ($row = $trendStmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
if (! isset($trendData[$row['date']])) {
|
||||
$trendData[$row['date']] = [];
|
||||
}
|
||||
$trendData[$row['date']][$row['feedback_type']] = (int)$row['count'];
|
||||
}
|
||||
|
||||
return [
|
||||
'total_count' => $totalCount,
|
||||
'by_feedback_type' => $typeStats,
|
||||
'by_category' => $categoryStats,
|
||||
'by_severity' => $severityStats,
|
||||
'trend_data' => $trendData,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRecentFeedback(int $limit = 10): array
|
||||
{
|
||||
$stmt = $this->pdo->prepare('
|
||||
SELECT
|
||||
detection_id, feedback_type, user_id, comment,
|
||||
timestamp, category, severity, context
|
||||
FROM waf_feedback
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT ?
|
||||
');
|
||||
|
||||
$stmt->execute([$limit]);
|
||||
|
||||
return $this->hydrateMultipleResults($stmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates multiple DetectionFeedback objects from a PDO statement
|
||||
*
|
||||
* @param \PDOStatement $stmt The executed PDO statement
|
||||
* @return DetectionFeedback[] Array of DetectionFeedback objects
|
||||
*/
|
||||
private function hydrateMultipleResults(\PDOStatement $stmt): array
|
||||
{
|
||||
$results = [];
|
||||
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$results[] = $this->hydrateFromRow($row);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates a DetectionFeedback object from a database row
|
||||
*
|
||||
* @param array $row Database row
|
||||
* @return DetectionFeedback
|
||||
*/
|
||||
private function hydrateFromRow(array $row): DetectionFeedback
|
||||
{
|
||||
return new DetectionFeedback(
|
||||
detectionId: $row['detection_id'],
|
||||
feedbackType: FeedbackType::from($row['feedback_type']),
|
||||
userId: $row['user_id'],
|
||||
comment: $row['comment'],
|
||||
timestamp: Timestamp::fromString($row['timestamp']),
|
||||
category: DetectionCategory::from($row['category']),
|
||||
severity: DetectionSeverity::from($row['severity']),
|
||||
context: json_decode($row['context'] ?? '{}', true) ?: []
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user