Simple latest comment list
[anoweco.git] / src / anoweco / Storage.php
1 <?php
2 namespace anoweco;
3
4 class Storage
5 {
6     public function __construct()
7     {
8         require __DIR__ . '/../../data/config.php';
9         $this->db = new \PDO($dbdsn, $dbuser, $dbpass);
10         $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
11     }
12
13     /**
14      * Store a new comment into the database
15      *
16      * @param object  $json   Micropub create JSON
17      * @param integer $userId ID of the user whom this comment belongs
18      *
19      * @return integer Comment ID
20      * @throws \Exception
21      */
22     public function addComment($json, $userId)
23     {
24         $stmt = $this->db->prepare(
25             'INSERT INTO comments SET'
26             . '  comment_user_id = :userId'
27             . ', comment_published = NOW()'
28             . ', comment_of_url = :ofUrl'
29             . ', comment_type = :type'
30             . ', comment_json = :json'
31         );
32
33         $ofUrl = '';
34         $type  = null;
35         if (isset($json->properties->{'in-reply-to'})) {
36             $ofUrl = reset($json->properties->{'in-reply-to'});
37             $type = 'reply';
38         } else if (isset($json->properties->{'like-of'})) {
39             $ofUrl = reset($json->properties->{'like-of'});
40             $type  = 'like';
41         } else {
42             throw new \Exception(
43                 'Invalid post type, only reply and like allowed',
44                 400
45             );
46         }
47
48         $stmt->execute(
49             array(
50                 ':userId' => $userId,
51                 ':ofUrl'  => $ofUrl,
52                 ':type'   => $type,
53                 ':json'   => json_encode($json),
54             )
55         );
56         return $this->db->lastInsertId();
57     }
58
59     /**
60      * @return null|object NULL if not found, JSON comment object otherwise
61      *                     - "Xrow" property contains the database row object
62      *                     - "user" property contains the user db row object
63      */
64     public function getJsonComment($id)
65     {
66         $stmt = $this->db->prepare(
67             'SELECT * FROM comments WHERE comment_id = ?'
68         );
69         $stmt->execute([$id]);
70         $row = $stmt->fetchObject();
71
72         if ($row === false) {
73             return null;
74         }
75
76         $json = json_decode($row->comment_json);
77         $json->Xrow = $row;
78         //FIXME: load user
79
80         $stmt = $this->db->prepare('SELECT * FROM users WHERE user_id = ?');
81         $stmt->execute([$row->comment_user_id]);
82         $rowUser = $stmt->fetchObject();
83         if ($rowUser === false) {
84             $rowUser = (object) array(
85                 'user_id'       => 0,
86                 'user_name'     => 'Anonymous',
87                 'user_imageurl' => '',
88             );
89         }
90
91         $json->user = $rowUser;
92         return $json;
93     }
94
95     /**
96      * @return null|object NULL if not found, JSON comment object otherwise
97      *                     - "Xrow" property contains the database row object
98      *                     - "user" property contains the user db row object
99      */
100     public function listLatest()
101     {
102         $stmt = $this->db->prepare(
103             'SELECT comment_id, comment_user_id, comment_published'
104             . ', comment_of_url, comment_type'
105             . ' FROM comments'
106             . ' ORDER BY comment_published DESC'
107             . ' LIMIT 20'
108         );
109         $stmt->execute();
110         $rows = $stmt->fetchAll(\PDO::FETCH_OBJ);
111         if (!count($rows)) {
112             return [];
113         }
114         $userIds = array_values(
115             array_unique(array_column($rows, 'comment_user_id'))
116         );
117
118
119         $placeholders = implode(',', array_fill(0, count($userIds), '?'));
120         $stmt = $this->db->prepare(
121             'SELECT * FROM users WHERE user_id IN (' . $placeholders . ')'
122         );
123         $stmt->execute($userIds);
124
125         $users = $stmt->fetchAll(\PDO::FETCH_OBJ);
126         $users = array_combine(
127             array_column($users, 'user_id'),
128             $users
129         );
130
131         foreach ($rows as $row) {
132             $row->user = $users[$row->comment_user_id];
133         }
134
135         return $rows;
136     }
137
138     /**
139      * @return null|object NULL if not found, user database row otherwise
140      */
141     public function getUser($id)
142     {
143         $stmt = $this->db->prepare(
144             'SELECT * FROM users WHERE user_id = ?'
145         );
146         $stmt->execute([$id]);
147         $row = $stmt->fetchObject();
148
149         if ($row === false) {
150             return null;
151         }
152         return $row;
153     }
154
155     public function findUser($name, $imageurl)
156     {
157         $stmt = $this->db->prepare(
158             'SELECT user_id FROM users'
159             . ' WHERE user_name = ? AND user_imageurl = ?'
160         );
161         $stmt->execute([$name, $imageurl]);
162         $row = $stmt->fetchObject();
163
164         if ($row === false) {
165             return null;
166         }
167         return $row->user_id;
168     }
169
170     public function createUser($name, $imageurl)
171     {
172         $stmt = $this->db->prepare(
173             'INSERT INTO users SET'
174             . '  user_name = :name'
175             . ', user_imageurl = :imageurl'
176         );
177         $stmt->execute(
178             array(
179                 ':name'     => $name,
180                 ':imageurl' => $imageurl,
181             )
182         );
183         return $this->db->lastInsertId();
184     }
185
186     public function setPostPingState($postId, $pingstate)
187     {
188         $stmt = $this->db->prepare(
189             'UPDATE comments SET comment_pingstate = ? WHERE comment_id = ?'
190         );
191         $stmt->execute(array($pingstate, $postId));
192     }
193 }
194 ?>