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