Passed
Push — master ( 9422eb...577871 )
by Gaetano
08:48
created

getComments()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 21
c 2
b 0
f 0
nc 6
nop 1
dl 0
loc 30
ccs 0
cts 19
cp 0
crap 30
rs 9.2728

1 Method

Rating   Name   Duplication   Size   Complexity  
A CommentManager::getComments() 0 17 2
1
<?php
2
/**
3
 * A basic comment server. Given an ID it will store a list of names and comment texts against it.
4
 * It uses a SQLite3 database for storage.
5
 *
6
 * The source code demonstrates:
7
 * - registration of php class methods as xml-rpc method handlers
8
 * - usage as method handlers of php code which is completely unaware of xml-rpc, via the Server's properties
9
 *   `$functions_parameters_type` and `$exception_handling`
10
 */
11 1
12
require_once __DIR__ . "/_prepend.php";
13 1
14
use PhpXmlRpc\Response;
15
use PhpXmlRpc\Server;
16
use PhpXmlRpc\Value;
17
18
class CommentManager
19
{
20
    protected $dbFile = "/tmp/comments.db";
21
22
    protected function createTable($db)
23
    {
24
        return $db->exec('CREATE TABLE IF NOT EXISTS comments (msg_id TEXT NOT NULL, name TEXT NOT NULL, comment TEXT NOT NULL)');
25
    }
26
27
    /**
28
     * NB: we know for a fact that this will be called with 3 string arguments because of the signature used to register
29
     * this method in the dispatch map. But nothing prevents the client from sending empty strings, nor sql-injection attempts!
30
     *
31
     * @param string $msgID
32
     * @param string $name
33
     * @param string $comment
34
     * @return int
35
     * @throws \Exception
36
     */
37
    public function addComment($msgID, $name, $comment)
38
    {
39
        $db = new SQLite3($this->dbFile);
40
        $this->createTable($db);
41
42
        $statement = $db->prepare("INSERT INTO comments VALUES(:msg_id, :name, :comment)");
43
        $statement->bindValue(':msg_id', $msgID);
44
        $statement->bindValue(':name', $name);
45
        $statement->bindValue(':comment', $comment);
46
        $statement->execute();
47
48
        /// @todo this insert-then-count is not really atomic - we should use a transaction
49
50
        $statement = $db->prepare("SELECT count(*) AS tot FROM comments WHERE msg_id = :id");
51
        $statement->bindValue(':id', $msgID);
52
        $results = $statement->execute();
53
        $row = $results->fetchArray(SQLITE3_ASSOC);
54
        $results->finalize();
55 1
        $count = $row['tot'];
56
57 1
        $db->close();
58
59
        return $count;
60
    }
61
62
    /**
63
     * NB: we know for a fact that this will be called with 1 strin arguments because of the signature used to register
64
     * this method in the dispatch map. But nothing prevents the client from sending empty strings, nor sql-injection attempts!
65
     *
66
     * @param string $msgID
67
     * @return Response|array[]
68
     * @throws \Exception
69
     */
70
    public function getComments($msgID)
71
    {
72
        $db = new SQLite3($this->dbFile);
73
        $this->createTable($db);
74
75
        $ra = array();
76
        $statement = $db->prepare("SELECT name, comment FROM comments WHERE msg_id = :id ORDER BY rowid");
77
        $statement->bindValue(':id', $msgID);
78
        $results = $statement->execute();
79
        while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
80
            $ra[] = $row;
81
        }
82
        $results->finalize();
83
84
        $db->close();
85
86
        return $ra;
87
    }
88
}
89
90
$manager = new CommentManager();
91
92
$addComment_sig = array(array(Value::$xmlrpcInt, Value::$xmlrpcString, Value::$xmlrpcString, Value::$xmlrpcString));
93
94
$addComment_doc = 'Adds a comment to an item. The first parameter is the item ID, the second the name of the commenter, ' .
95
    'and the third is the comment itself. Returns the number of comments against that ID.';
96
97 1
$getComments_sig = array(array(Value::$xmlrpcArray, Value::$xmlrpcString));
98
99 1
$getComments_doc = 'Returns an array of comments for a given ID, which is the sole argument. Each array item is a struct ' .
100 1
    'containing name and comment text.';
101 1
102
// NB: take care not to output anything else after this call, as it will mess up the responses and it will be hard to
103
// debug. In case you have to do so, at least re-emit a correct Content-Length http header (requires output buffering)
104 1
$srv = new Server(array(
105 1
    "discuss.addComment" => array(
106 1
        "function" => array($manager, "addComment"),
107
        "signature" => $addComment_sig,
108
        "docstring" => $addComment_doc,
109
    ),
110 1
    "discuss.getComments" => array(
111
        "function" => array($manager, "getComments"),
112
        "signature" => $getComments_sig,
113
        "docstring" => $getComments_doc,
114
    ),
115
), false);
116
117
// let the xml=rpc server know that the method-handler functions expect plain php values
118
$srv->functions_parameters_type = 'phpvals';
119
120
// let code exceptions float all the way to the remote caller as xml-rpc faults - it helps debugging
121
$srv->exception_handling = 1;
122
123
$srv->service();
124