1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* A basic comment server. Given an ID it will store a list of names and comment texts against it. |
5
|
|
|
* It uses a SQLite3 database for storage. |
6
|
|
|
* NB: this class is totally unaware of the existence of xml-rpc or phpxmlrpc. |
7
|
|
|
*/ |
8
|
|
|
class CommentManager |
9
|
|
|
{ |
10
|
|
|
protected $dbFile = "/tmp/comments.db"; |
11
|
|
|
|
12
|
|
|
protected function createTable($db) |
13
|
|
|
{ |
14
|
|
|
return $db->exec('CREATE TABLE IF NOT EXISTS comments (msg_id TEXT NOT NULL, name TEXT NOT NULL, comment TEXT NOT NULL)'); |
15
|
|
|
} |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* NB: we know for a fact that this will be called with 3 string arguments because of the signature used to register |
19
|
|
|
* this method in the dispatch map. But nothing prevents the client from sending empty strings, nor sql-injection attempts! |
20
|
|
|
* |
21
|
|
|
* @param string $msgID |
22
|
|
|
* @param string $name username |
23
|
|
|
* @param string $comment comment text |
24
|
|
|
* @return int the number of comments for the given message |
25
|
|
|
* @throws \Exception |
26
|
|
|
*/ |
27
|
|
|
public function addComment($msgID, $name, $comment) |
28
|
|
|
{ |
29
|
|
|
$db = new SQLite3($this->dbFile); |
30
|
|
|
$this->createTable($db); |
31
|
|
|
|
32
|
|
|
$statement = $db->prepare("INSERT INTO comments VALUES(:msg_id, :name, :comment)"); |
33
|
|
|
$statement->bindValue(':msg_id', $msgID); |
34
|
|
|
$statement->bindValue(':name', $name); |
35
|
|
|
$statement->bindValue(':comment', $comment); |
36
|
|
|
$statement->execute(); |
37
|
|
|
|
38
|
|
|
/// @todo this insert-then-count is not really atomic - we should use a transaction |
39
|
|
|
|
40
|
|
|
$statement = $db->prepare("SELECT count(*) AS tot FROM comments WHERE msg_id = :id"); |
41
|
|
|
$statement->bindValue(':id', $msgID); |
42
|
|
|
$results = $statement->execute(); |
43
|
|
|
$row = $results->fetchArray(SQLITE3_ASSOC); |
44
|
|
|
$results->finalize(); |
45
|
|
|
$count = $row['tot']; |
46
|
|
|
|
47
|
|
|
$db->close(); |
48
|
|
|
|
49
|
|
|
return $count; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* NB: we know for a fact that this will be called with 1 string arguments because of the signature used to register |
54
|
|
|
* this method in the dispatch map. But nothing prevents the client from sending empty strings, nor sql-injection attempts! |
55
|
|
|
* |
56
|
|
|
* @param string $msgID |
57
|
|
|
* @return array[] each element is a struct, with elements 'name', 'comment' |
58
|
|
|
* @throws \Exception |
59
|
|
|
*/ |
60
|
|
|
public function getComments($msgID) |
61
|
|
|
{ |
62
|
|
|
$db = new SQLite3($this->dbFile); |
63
|
|
|
$this->createTable($db); |
64
|
|
|
|
65
|
|
|
$ra = array(); |
66
|
|
|
$statement = $db->prepare("SELECT name, comment FROM comments WHERE msg_id = :id ORDER BY rowid"); |
67
|
|
|
$statement->bindValue(':id', $msgID); |
68
|
|
|
$results = $statement->execute(); |
69
|
|
|
while ($row = $results->fetchArray(SQLITE3_ASSOC)) { |
70
|
|
|
$ra[] = $row; |
71
|
|
|
} |
72
|
|
|
$results->finalize(); |
73
|
|
|
|
74
|
|
|
$db->close(); |
75
|
|
|
|
76
|
|
|
return $ra; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|