-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDatabase.php
More file actions
130 lines (109 loc) · 3.71 KB
/
Copy pathDatabase.php
File metadata and controls
130 lines (109 loc) · 3.71 KB
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
<?php
require 'utils.php';
class Database
{
protected PDO $pdo;
public function __construct(string $file = 'scraper.db')
{
$this->pdo = new PDO("sqlite:$file");
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function execFile(string $file): void
{
$this->pdo->exec(file_get_contents($file));
}
/* ---------- TENANTS ---------- */
public function saveTenant(string $domain): void
{
$stmt = $this->pdo->prepare(
"INSERT OR IGNORE INTO tenants VALUES (?, ?)"
);
$stmt->execute([$domain, date('c')]);
}
public function getTenants(): array
{
return $this->pdo
->query("SELECT domain FROM tenants")
->fetchAll(PDO::FETCH_COLUMN);
}
/* ---------- JOBS ---------- */
public function jobExists(string $jobId, string $tenant): bool
{
$stmt = $this->pdo->prepare(
"SELECT 1 FROM jobs WHERE job_id=? AND tenant=?"
);
$stmt->execute([$jobId, $tenant]);
return (bool)$stmt->fetchColumn();
}
public function saveJobsBatch(array $jobs): void
{
$this->pdo->beginTransaction();
try {
foreach ($jobs as $job) {
$this->saveJob($job);
}
$this->pdo->commit();
} catch (Exception $e) {
$this->pdo->rollBack();
throw $e;
}
}
public function saveJob(array $job): void
{
$stmt = $this->pdo->prepare(
"INSERT OR IGNORE INTO jobs
(job_id, tenant, title, description, location, date_posted, apply_url, metadata, scraped_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
$metadata = $job['metadata'] ?? [];
// Find date from multiple possible field names
$datePosted = find_in_array($metadata, 'date')
?? find_in_array($metadata, 'posted')
?? find_in_array($metadata, 'created')
?? null;
// Find location from multiple possible field names
$location = find_in_array($metadata, 'location')
?? find_in_array($metadata, 'place')
?? find_in_array($metadata, 'city')
?? find_in_array($metadata, 'country')
?? null;
$stmt->execute([
$job['job_id'],
$job['tenant'],
$job['metadata']['job_title'] ?? $job['title'] ?? null,
$job['description_html'] ?? null,
$location,
$datePosted,
$job['job_url'] ?? null,
json_encode($metadata, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
date('c')
]);
}
/* ---------- RESUME SUPPORT ---------- */
public function getState(string $tenant): array
{
$stmt = $this->pdo->prepare(
"SELECT last_offset, completed FROM crawl_state WHERE tenant=?"
);
$stmt->execute([$tenant]);
return $stmt->fetch(PDO::FETCH_ASSOC) ?: ['last_offset' => 0, 'completed' => 0];
}
public function updateState(string $tenant, int $offset, bool $done = false): void
{
$stmt = $this->pdo->prepare(
"INSERT INTO crawl_state (tenant, last_offset, completed)
VALUES (?, ?, ?)
ON CONFLICT(tenant) DO UPDATE SET
last_offset=excluded.last_offset,
completed=excluded.completed"
);
$stmt->execute([$tenant, $offset, $done ? 1 : 0]);
}
/* ---------- EXPORT ---------- */
public function getAllJobs(): array
{
return $this->pdo
->query("SELECT * FROM jobs ORDER BY scraped_at DESC")
->fetchAll(PDO::FETCH_ASSOC);
}
}