1
|
|
|
<?php namespace XoopsModules\Smartfaq; |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Module: SmartFAQ |
5
|
|
|
* Author: The SmartFactory <www.smartfactory.ca> |
6
|
|
|
* Licence: GNU |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
use XoopsModules\Smartfaq; |
10
|
|
|
use XoopsModules\Smartfaq\Constants; |
11
|
|
|
|
12
|
|
|
// defined('XOOPS_ROOT_PATH') || die('Restricted access'); |
|
|
|
|
13
|
|
|
|
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Answers handler class. |
17
|
|
|
* This class is responsible for providing data access mechanisms to the data source |
18
|
|
|
* of Answer class objects. |
19
|
|
|
* |
20
|
|
|
* @author marcan <[email protected]> |
21
|
|
|
* @package SmartFAQ |
22
|
|
|
*/ |
23
|
|
|
class AnswerHandler extends \XoopsPersistableObjectHandler |
24
|
|
|
{ |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* create a new answer |
28
|
|
|
* |
29
|
|
|
* @param bool $isNew flag the new objects as "new"? |
30
|
|
|
* @return object Answer |
31
|
|
|
*/ |
32
|
|
|
public function create($isNew = true) |
33
|
|
|
{ |
34
|
|
|
$answer = new Smartfaq\Answer(); |
35
|
|
|
if ($isNew) { |
36
|
|
|
$answer->setNew(); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
return $answer; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* retrieve an answer |
44
|
|
|
* |
45
|
|
|
* @param int $id answerid of the answer |
|
|
|
|
46
|
|
|
* @param null $fields |
47
|
|
|
* @return mixed reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object, FALSE if failed |
48
|
|
|
*/ |
49
|
|
View Code Duplication |
public function get($id = null, $fields = null) |
|
|
|
|
50
|
|
|
{ |
51
|
|
|
if ((int)$id > 0) { |
52
|
|
|
$sql = 'SELECT * FROM ' . $this->db->prefix('smartfaq_answers') . ' WHERE answerid=' . $id; |
53
|
|
|
if (!$result = $this->db->query($sql)) { |
54
|
|
|
return false; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
$numrows = $this->db->getRowsNum($result); |
58
|
|
|
if (1 == $numrows) { |
59
|
|
|
$answer = new Smartfaq\Answer(); |
60
|
|
|
$answer->assignVars($this->db->fetchArray($result)); |
61
|
|
|
|
62
|
|
|
return $answer; |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
return false; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* insert a new answer in the database |
71
|
|
|
* |
72
|
|
|
* @param \XoopsObject $answerObj reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object |
73
|
|
|
* @param bool $force |
74
|
|
|
* @return bool FALSE if failed, TRUE if already present and unchanged or successful |
75
|
|
|
*/ |
76
|
|
|
public function insert(\XoopsObject $answerObj, $force = false) |
77
|
|
|
{ |
78
|
|
|
if ('xoopsmodules\smartfaq\answer' !== strtolower(get_class($answerObj))) { |
79
|
|
|
return false; |
80
|
|
|
} |
81
|
|
|
if (!$answerObj->isDirty()) { |
82
|
|
|
return true; |
83
|
|
|
} |
84
|
|
|
if (!$answerObj->cleanVars()) { |
85
|
|
|
return false; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
foreach ($answerObj->cleanVars as $k => $v) { |
89
|
|
|
${$k} = $v; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
if ($answerObj->isNew()) { |
93
|
|
|
$sql = sprintf('INSERT INTO %s (answerid, `status`, faqid, answer, uid, datesub, notifypub) VALUES (NULL, %u, %u, %s, %u, %u, %u)', $this->db->prefix('smartfaq_answers'), $status, $faqid, $this->db->quoteString($answer), $uid, time(), $notifypub); |
|
|
|
|
94
|
|
|
} else { |
95
|
|
|
$sql = sprintf('UPDATE %s SET STATUS = %u, faqid = %s, answer = %s, uid = %u, datesub = %u, notifypub = %u WHERE answerid = %u', $this->db->prefix('smartfaq_answers'), $status, $faqid, $this->db->quoteString($answer), $uid, $datesub, $notifypub, $answerid); |
|
|
|
|
96
|
|
|
} |
97
|
|
|
|
98
|
|
View Code Duplication |
if (false !== $force) { |
|
|
|
|
99
|
|
|
$result = $this->db->queryF($sql); |
100
|
|
|
} else { |
101
|
|
|
$result = $this->db->query($sql); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
if (!$result) { |
105
|
|
|
return false; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
if ($answerObj->isNew()) { |
109
|
|
|
$answerObj->assignVar('answerid', $this->db->getInsertId()); |
110
|
|
|
} else { |
111
|
|
|
$answerObj->assignVar('answerid', $answerid); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
return true; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* delete an answer from the database |
119
|
|
|
* |
120
|
|
|
* @param \XoopsObject $answer reference to the answer to delete |
121
|
|
|
* @param bool $force |
122
|
|
|
* @return bool FALSE if failed. |
123
|
|
|
*/ |
124
|
|
|
public function delete(\XoopsObject $answer, $force = false) |
125
|
|
|
{ |
126
|
|
|
if ('xoopsmodules\smartfaq\answer' !== strtolower(get_class($answer))) { |
127
|
|
|
return false; |
128
|
|
|
} |
129
|
|
|
$sql = sprintf('DELETE FROM %s WHERE answerid = %u', $this->db->prefix('smartfaq_answers'), $answer->getVar('answerid')); |
130
|
|
|
|
131
|
|
|
//echo "<br>" . $sql . "<br>"; |
|
|
|
|
132
|
|
|
|
133
|
|
View Code Duplication |
if (false !== $force) { |
|
|
|
|
134
|
|
|
$result = $this->db->queryF($sql); |
135
|
|
|
} else { |
136
|
|
|
$result = $this->db->query($sql); |
137
|
|
|
} |
138
|
|
|
if (!$result) { |
139
|
|
|
return false; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return true; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* delete an answer from the database |
147
|
|
|
* |
148
|
|
|
* @param object $faqObj reference to the answer to delete |
149
|
|
|
* @return bool FALSE if failed. |
150
|
|
|
* @internal param bool $force |
151
|
|
|
*/ |
152
|
|
|
public function deleteFaqAnswers($faqObj) |
153
|
|
|
{ |
154
|
|
|
if ('xoopsmodules\smartfaq\faq' !== strtolower(get_class($faqObj))) { |
155
|
|
|
return false; |
156
|
|
|
} |
157
|
|
|
$answers = $this->getAllAnswers($faqObj->faqid()); |
158
|
|
|
$result = true; |
159
|
|
|
foreach ($answers as $answer) { |
160
|
|
|
if (!$this->delete($answer)) { |
161
|
|
|
$result = false; |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
return $result; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* retrieve answers from the database |
170
|
|
|
* |
171
|
|
|
* @param \CriteriaElement $criteria {@link CriteriaElement} conditions to be met |
|
|
|
|
172
|
|
|
* @param bool $id_as_key use the answerid as key for the array? |
173
|
|
|
* @param bool $as_object |
174
|
|
|
* @return array array of <a href='psi_element://sfAnswer'>sfAnswer</a> objects |
175
|
|
|
*/ |
176
|
|
View Code Duplication |
public function &getObjects(\CriteriaElement $criteria = null, $id_as_key = false, $as_object = true) |
|
|
|
|
177
|
|
|
{ |
178
|
|
|
$ret = []; |
179
|
|
|
$limit = $start = 0; |
180
|
|
|
$sql = 'SELECT * FROM ' . $this->db->prefix('smartfaq_answers'); |
181
|
|
|
if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) { |
|
|
|
|
182
|
|
|
$sql .= ' ' . $criteria->renderWhere(); |
183
|
|
|
if ('' != $criteria->getSort()) { |
184
|
|
|
$sql .= ' ORDER BY ' . $criteria->getSort() . ' ' . $criteria->getOrder(); |
185
|
|
|
} |
186
|
|
|
$limit = $criteria->getLimit(); |
187
|
|
|
$start = $criteria->getStart(); |
188
|
|
|
} |
189
|
|
|
//echo "<br>" . $sql . "<br>"; |
|
|
|
|
190
|
|
|
$result = $this->db->query($sql, $limit, $start); |
191
|
|
|
if (!$result) { |
192
|
|
|
return $ret; |
193
|
|
|
} |
194
|
|
|
while (false !== ($myrow = $this->db->fetchArray($result))) { |
195
|
|
|
$answer = new Smartfaq\Answer(); |
196
|
|
|
$answer->assignVars($myrow); |
197
|
|
|
if (!$id_as_key) { |
198
|
|
|
$ret[] =& $answer; |
199
|
|
|
} else { |
200
|
|
|
$ret[$myrow['answerid']] = $answer; |
201
|
|
|
} |
202
|
|
|
unset($answer); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
return $ret; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* retrieve 1 official answer (for now SmartFAQ only allow 1 official answer...) |
210
|
|
|
* |
211
|
|
|
* @param int $faqid |
212
|
|
|
* @return mixed reference to the <a href='psi_element://sfAnswer'>sfAnswer</a> object, FALSE if failed |
213
|
|
|
*/ |
214
|
|
|
public function getOfficialAnswer($faqid = 0) |
215
|
|
|
{ |
216
|
|
|
$theaAnswers = $this->getAllAnswers($faqid, Constants::SF_AN_STATUS_APPROVED, 1, 0); |
217
|
|
|
$ret = false; |
218
|
|
|
if (1 == count($theaAnswers)) { |
219
|
|
|
$ret = $theaAnswers[0]; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
return $ret; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* retrieve all answers |
227
|
|
|
* |
228
|
|
|
* @param int $faqid |
229
|
|
|
* @param int $status |
230
|
|
|
* @param int $limit |
231
|
|
|
* @param int $start |
232
|
|
|
* @param string $sort |
233
|
|
|
* @param string $order |
234
|
|
|
* @return array array of <a href='psi_element://sfAnswer'>sfAnswer</a> objects |
235
|
|
|
*/ |
236
|
|
|
public function getAllAnswers( |
237
|
|
|
$faqid = 0, |
238
|
|
|
$status = -1, |
239
|
|
|
$limit = 0, |
240
|
|
|
$start = 0, |
241
|
|
|
$sort = 'datesub', |
242
|
|
|
$order = 'DESC' |
243
|
|
|
) { |
244
|
|
|
$hasStatusCriteria = false; |
245
|
|
|
$criteriaStatus = new \CriteriaCompo(); |
246
|
|
|
if (is_array($status)) { |
247
|
|
|
$hasStatusCriteria = true; |
248
|
|
|
foreach ($status as $v) { |
249
|
|
|
$criteriaStatus->add(new \Criteria('status', $v), 'OR'); |
250
|
|
|
} |
251
|
|
|
} elseif (-1 != $status) { |
252
|
|
|
$hasStatusCriteria = true; |
253
|
|
|
$criteriaStatus->add(new \Criteria('status', $status), 'OR'); |
254
|
|
|
} |
255
|
|
|
$criteriaFaqid = new \Criteria('faqid', $faqid); |
256
|
|
|
|
257
|
|
|
$criteria = new \CriteriaCompo(); |
258
|
|
|
$criteria->add($criteriaFaqid); |
259
|
|
|
|
260
|
|
|
if ($hasStatusCriteria) { |
261
|
|
|
$criteria->add($criteriaStatus); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$criteria->setSort($sort); |
265
|
|
|
$criteria->setOrder($order); |
266
|
|
|
$criteria->setLimit($limit); |
267
|
|
|
$criteria->setStart($start); |
268
|
|
|
$ret =& $this->getObjects($criteria); |
269
|
|
|
|
270
|
|
|
return $ret; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* count answers matching a condition |
275
|
|
|
* |
276
|
|
|
* @param \CriteriaElement $criteria {@link CriteriaElement} to match |
|
|
|
|
277
|
|
|
* @return int count of answers |
278
|
|
|
*/ |
279
|
|
View Code Duplication |
public function getCount(\CriteriaElement $criteria = null) |
|
|
|
|
280
|
|
|
{ |
281
|
|
|
$sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('smartfaq_answers'); |
282
|
|
|
if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) { |
|
|
|
|
283
|
|
|
$sql .= ' ' . $criteria->renderWhere(); |
284
|
|
|
} |
285
|
|
|
$result = $this->db->query($sql); |
286
|
|
|
if (!$result) { |
287
|
|
|
return 0; |
288
|
|
|
} |
289
|
|
|
list($count) = $this->db->fetchRow($result); |
290
|
|
|
|
291
|
|
|
return $count; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* count answers matching a condition and group by faq ID |
296
|
|
|
* |
297
|
|
|
* @param object $criteria {@link CriteriaElement} to match |
|
|
|
|
298
|
|
|
* @return array |
299
|
|
|
*/ |
300
|
|
|
public function getCountByFAQ($criteria = null) |
301
|
|
|
{ |
302
|
|
|
$sql = 'SELECT faqid, COUNT(*) FROM ' . $this->db->prefix('smartfaq_answers'); |
303
|
|
|
if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) { |
|
|
|
|
304
|
|
|
$sql .= ' ' . $criteria->renderWhere(); |
305
|
|
|
$sql .= ' ' . $criteria->getGroupby(); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
//echo "<br>$sql<br>"; |
309
|
|
|
|
310
|
|
|
$result = $this->db->query($sql); |
311
|
|
|
if (!$result) { |
312
|
|
|
return []; |
313
|
|
|
} |
314
|
|
|
$ret = []; |
315
|
|
|
while (list($id, $count) = $this->db->fetchRow($result)) { |
316
|
|
|
$ret[$id] = $count; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
return $ret; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* delete answers matching a set of conditions |
324
|
|
|
* |
325
|
|
|
* @param \CriteriaElement $criteria {@link CriteriaElement} |
|
|
|
|
326
|
|
|
* @param bool $force |
327
|
|
|
* @param bool $asObject |
328
|
|
|
* @return bool FALSE if deletion failed |
329
|
|
|
*/ |
330
|
|
|
public function deleteAll(\CriteriaElement $criteria = null, $force = true, $asObject = false) |
331
|
|
|
{ |
332
|
|
|
$sql = 'DELETE FROM ' . $this->db->prefix('smartfaq_answers'); |
333
|
|
|
if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) { |
|
|
|
|
334
|
|
|
$sql .= ' ' . $criteria->renderWhere(); |
335
|
|
|
} |
336
|
|
|
if (!$this->db->query($sql)) { |
337
|
|
|
return false; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
return true; |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* Change a value for answers with a certain criteria |
345
|
|
|
* |
346
|
|
|
* @param string $fieldname Name of the field |
347
|
|
|
* @param string $fieldvalue Value to write |
348
|
|
|
* @param \CriteriaElement $criteria {@link CriteriaElement} |
|
|
|
|
349
|
|
|
* @param bool $force |
350
|
|
|
* @return bool |
351
|
|
|
*/ |
352
|
|
View Code Duplication |
public function updateAll($fieldname, $fieldvalue, \CriteriaElement $criteria = null, $force = false) |
|
|
|
|
353
|
|
|
{ |
354
|
|
|
$set_clause = is_numeric($fieldvalue) ? $fieldname . ' = ' . $fieldvalue : $fieldname . ' = ' . $this->db->quoteString($fieldvalue); |
355
|
|
|
$sql = 'UPDATE ' . $this->db->prefix('smartfaq_answers') . ' SET ' . $set_clause; |
356
|
|
|
if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) { |
|
|
|
|
357
|
|
|
$sql .= ' ' . $criteria->renderWhere(); |
358
|
|
|
} |
359
|
|
|
//echo "<br>" . $sql . "<br>"; |
|
|
|
|
360
|
|
|
if (!$this->db->queryF($sql)) { |
361
|
|
|
return false; |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
return true; |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* @param $faqids |
369
|
|
|
* @return array |
370
|
|
|
*/ |
371
|
|
|
public function getLastPublishedByFaq($faqids) |
372
|
|
|
{ |
373
|
|
|
$ret = []; |
374
|
|
|
$sql = 'SELECT faqid, answer, uid, datesub FROM ' . $this->db->prefix('smartfaq_answers') . ' |
375
|
|
|
WHERE faqid IN (' . implode(',', $faqids) . ') AND status = ' . Constants::SF_AN_STATUS_APPROVED . ' GROUP BY faqid'; |
376
|
|
|
$result = $this->db->query($sql); |
377
|
|
|
if (!$result) { |
378
|
|
|
return $ret; |
379
|
|
|
} |
380
|
|
View Code Duplication |
while ($row = $this->db->fetchArray($result)) { |
|
|
|
|
381
|
|
|
$answer = new Smartfaq\Answer(); |
382
|
|
|
$answer->assignVars($row); |
383
|
|
|
$ret[$row['faqid']] =& $answer; |
384
|
|
|
unset($answer); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
return $ret; |
388
|
|
|
} |
389
|
|
|
} |
390
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.