{
"event": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Crawler\/CrawlerPageRepository.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Crawler;\n\n\/\/ @responsibility: Lesezugriff auf crawler.pages (Liste\/Detail inkl. URL-Join)\n\nuse Domain\\Crawler\\PageDetail;\nuse Domain\\Crawler\\PageSummary;\n\nfinal class CrawlerPageRepository\n{\n public function __construct(private \\PDO $pdo)\n {\n }\n\n \/**\n * @return list<PageSummary>\n *\/\n public function listByCrawl(int $crawlId, int $limit = 200, int $offset = 0): array\n {\n $sql = 'SELECT p.id, p.crawl_id, p.url_id, u.url, p.http_status, p.title,'\n . ' p.meta_description, p.h1_count, p.word_count, p.render_mode,'\n . ' JSON_LENGTH(p.quality_flags) AS flag_count'\n . ' FROM pages p JOIN urls u ON u.id = p.url_id'\n . ' WHERE p.crawl_id = :crawl_id'\n . ' ORDER BY p.id LIMIT :limit OFFSET :offset';\n $stmt = $this->pdo->prepare($sql);\n $stmt->bindValue(':crawl_id', $crawlId, \\PDO::PARAM_INT);\n $stmt->bindValue(':limit', $limit, \\PDO::PARAM_INT);\n $stmt->bindValue(':offset', $offset, \\PDO::PARAM_INT);\n $stmt->execute();\n\n return array_map([$this, 'hydrateSummary'], $stmt->fetchAll());\n }\n\n public function find(int $pageId): ?PageDetail\n {\n $sql = 'SELECT p.*, u.url FROM pages p'\n . ' JOIN urls u ON u.id = p.url_id WHERE p.id = :id';\n $stmt = $this->pdo->prepare($sql);\n $stmt->execute([':id' => $pageId]);\n $row = $stmt->fetch();\n\n return $row !== false ? $this->hydrateDetail($row) : null;\n }\n\n \/**\n * @param array<string, mixed> $row\n *\/\n private function hydrateSummary(array $row): PageSummary\n {\n return new PageSummary(\n id: (int) $row['id'],\n crawlId: (int) $row['crawl_id'],\n urlId: (int) $row['url_id'],\n url: (string) $row['url'],\n httpStatus: $row['http_status'] !== null ? (int) $row['http_status'] : null,\n title: $row['title'] !== null ? (string) $row['title'] : null,\n metaDescription: $row['meta_description'] !== null\n ? (string) $row['meta_description'] : null,\n h1Count: (int) ($row['h1_count'] ?? 0),\n wordCount: (int) ($row['word_count'] ?? 0),\n renderMode: (string) $row['render_mode'],\n qualityFlagCount: (int) ($row['flag_count'] ?? 0),\n );\n }\n\n \/**\n * @param array<string, mixed> $row\n *\/\n private function hydrateDetail(array $row): PageDetail\n {\n $flagsRaw = $row['quality_flags'] !== null ? (string) $row['quality_flags'] : '[]';\n $flags = json_decode($flagsRaw, true, flags: JSON_THROW_ON_ERROR);\n\n return new PageDetail(\n id: (int) $row['id'],\n crawlId: (int) $row['crawl_id'],\n url: (string) $row['url'],\n fetchedAt: (string) $row['fetched_at'],\n renderMode: (string) $row['render_mode'],\n flags: is_array($flags) ? $flags : [],\n rawRow: $row,\n );\n }\n}\n"
}
}
{
"tool_response": {
"type": "create",
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Crawler\/CrawlerPageRepository.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Crawler;\n\n\/\/ @responsibility: Lesezugriff auf crawler.pages (Liste\/Detail inkl. URL-Join)\n\nuse Domain\\Crawler\\PageDetail;\nuse Domain\\Crawler\\PageSummary;\n\nfinal class CrawlerPageRepository\n{\n public function __construct(private \\PDO $pdo)\n {\n }\n\n \/**\n * @return list<PageSummary>\n *\/\n public function listByCrawl(int $crawlId, int $limit = 200, int $offset = 0): array\n {\n $sql = 'SELECT p.id, p.crawl_id, p.url_id, u.url, p.http_status, p.title,'\n . ' p.meta_description, p.h1_count, p.word_count, p.render_mode,'\n . ' JSON_LENGTH(p.quality_flags) AS flag_count'\n . ' FROM pages p JOIN urls u ON u.id = p.url_id'\n . ' WHERE p.crawl_id = :crawl_id'\n . ' ORDER BY p.id LIMIT :limit OFFSET :offset';\n $stmt = $this->pdo->prepare($sql);\n $stmt->bindValue(':crawl_id', $crawlId, \\PDO::PARAM_INT);\n $stmt->bindValue(':limit', $limit, \\PDO::PARAM_INT);\n $stmt->bindValue(':offset', $offset, \\PDO::PARAM_INT);\n $stmt->execute();\n\n return array_map([$this, 'hydrateSummary'], $stmt->fetchAll());\n }\n\n public function find(int $pageId): ?PageDetail\n {\n $sql = 'SELECT p.*, u.url FROM pages p'\n . ' JOIN urls u ON u.id = p.url_id WHERE p.id = :id';\n $stmt = $this->pdo->prepare($sql);\n $stmt->execute([':id' => $pageId]);\n $row = $stmt->fetch();\n\n return $row !== false ? $this->hydrateDetail($row) : null;\n }\n\n \/**\n * @param array<string, mixed> $row\n *\/\n private function hydrateSummary(array $row): PageSummary\n {\n return new PageSummary(\n id: (int) $row['id'],\n crawlId: (int) $row['crawl_id'],\n urlId: (int) $row['url_id'],\n url: (string) $row['url'],\n httpStatus: $row['http_status'] !== null ? (int) $row['http_status'] : null,\n title: $row['title'] !== null ? (string) $row['title'] : null,\n metaDescription: $row['meta_description'] !== null\n ? (string) $row['meta_description'] : null,\n h1Count: (int) ($row['h1_count'] ?? 0),\n wordCount: (int) ($row['word_count'] ?? 0),\n renderMode: (string) $row['render_mode'],\n qualityFlagCount: (int) ($row['flag_count'] ?? 0),\n );\n }\n\n \/**\n * @param array<string, mixed> $row\n *\/\n private function hydrateDetail(array $row): PageDetail\n {\n $flagsRaw = $row['quality_flags'] !== null ? (string) $row['quality_flags'] : '[]';\n $flags = json_decode($flagsRaw, true, flags: JSON_THROW_ON_ERROR);\n\n return new PageDetail(\n id: (int) $row['id'],\n crawlId: (int) $row['crawl_id'],\n url: (string) $row['url'],\n fetchedAt: (string) $row['fetched_at'],\n renderMode: (string) $row['render_mode'],\n flags: is_array($flags) ? $flags : [],\n rawRow: $row,\n );\n }\n}\n",
"structuredPatch": [],
"originalFile": null,
"userModified": false
}
}