This repository was archived by the owner on Jun 18, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathReportCollection.php
More file actions
334 lines (283 loc) · 9.9 KB
/
Copy pathReportCollection.php
File metadata and controls
334 lines (283 loc) · 9.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
<?php
namespace Foolz\FoolFuuka\Model;
use Foolz\Cache\Cache;
use Foolz\FoolFrame\Model\DoctrineConnection;
use Foolz\FoolFrame\Model\Model;
use Foolz\FoolFrame\Model\Uri;
use Foolz\Plugin\PlugSuit;
class ReportCollection extends Model
{
use PlugSuit;
/**
* An array of preloaded moderation
*
* @var array|null
*/
protected $preloaded = null;
/**
* @var DoctrineConnection
*/
protected $dc;
/**
* @var Uri
*/
protected $uri;
/**
* @var RadixCollection
*/
protected $radix_coll;
/**
* @var MediaFactory
*/
protected $media_factory;
/**
* @var BanFactory
*/
protected $ban_factory;
public function __construct(\Foolz\FoolFrame\Model\Context $context)
{
parent::__construct($context);
$this->dc = $context->getService('doctrine');
$this->uri = $context->getService('uri');
$this->radix_coll = $context->getService('foolfuuka.radix_collection');
$this->media_factory = $context->getService('foolfuuka.media_factory');
$this->ban_factory = $context->getService('foolfuuka.ban_factory');
$this->preload();
}
/**
* Creates a Report object from an associative array
*
* @param array $array An associative array
* @return \Foolz\FoolFuuka\Model\Report
*/
public function fromArray(array $array)
{
$new = new Report($this->getContext());
foreach ($array as $key => $item) {
$new->$key = $item;
}
$new->reason_processed = htmlentities(@iconv('UTF-8', 'UTF-8//IGNORE', $new->reason));
if (!isset($new->radix)) {
$new->radix = $this->radix_coll->getById($new->board_id);
}
return $new;
}
/**
* Takes an array of associative arrays to create an array of Report
*
* @param array $array An array of associative arrays, typically the result of a getAll
* @return array An array of Report
*/
public function fromArrayDeep(array $array)
{
$result = [];
foreach ($array as $item) {
$result[] = $this->fromArray($item);
}
return $result;
}
/**
* Loads all the moderation from the cache or the database
*/
public function p_preload()
{
if ($this->preloaded !== null) {
return;
}
try {
$this->preloaded = Cache::item('foolfuuka.model.report.preload.preloaded')->get();
} catch (\OutOfBoundsException $e) {
$this->preloaded = $this->dc->qb()
->select('*')
->from($this->dc->p('reports'), 'r')
->execute()
->fetchAll();
Cache::item('foolfuuka.model.report.preload.preloaded')->set($this->preloaded, 1800);
}
}
/**
* Clears the cached objects for the entire class
*/
public function p_clearCache()
{
$this->preloaded = null;
Cache::item('foolfuuka.model.report.preload.preloaded')->delete();
}
/**
* Returns an array of Reports by a comment's doc_id
*
* @param \Foolz\FoolFuuka\Model\Radix $board The Radix on which the Comment resides
* @param int $doc_id The doc_id of the Comment
*
* @return array An array of \Foolz\FoolFuuka\Model\Report
*/
public function getByDocId($radix, $doc_id)
{
$this->preload();
$result = [];
foreach ($this->preloaded as $item) {
if ($item['board_id'] === $radix->id && $item['doc_id'] === $doc_id) {
$result[] = $item;
}
}
return $this->fromArrayDeep($result);
}
/**
* Returns an array of Reports by a Media's media_id
*
* @param \Foolz\FoolFuuka\Model\Radix $board The Radix on which the Comment resides
* @param int $media_id The media_id of the Media
*
* @return array An array of \Foolz\FoolFuuka\Model\Report
*/
public function getByMediaId($radix, $media_id)
{
$this->preload();
$result = [];
foreach ($this->preloaded as $item) {
if ($item['board_id'] === $radix->id && $item['media_id'] === $media_id) {
$result[] = $item;
}
}
return $this->fromArrayDeep($result);
}
/**
* Fetches and returns all the Reports
*
* @return array An array of Report
*/
public function getAll()
{
$this->preload();
return $this->fromArrayDeep($this->preloaded);
}
/**
* Returns the number of Reports
*
* @return int The number of Report
*/
public function count()
{
$this->preload();
return count($this->preloaded);
}
public function validateUserReport($report)
{
// check how many moderation have been sent in the last hour to prevent spam
$reported = $this->dc->qb()
->select('COUNT(*) as count')
->from($this->dc->p('reports'), 'r')
->where('created > :time')
->andWhere('ip_reporter = :ip_reporter')
->setParameter(':time', time() - 86400)
->setParameter(':ip_reporter', $report->ip_reporter)
->execute()
->fetch();
if ($reported['count'] > 25) {
throw new ReportSentTooManyException(_i('You have submitted too many reports within an hour.'));
}
$submitted = $this->dc->qb()
->select('COUNT(*) as count')
->from($this->dc->p('reports'), 'r')
->where('board_id = :board_id')
->andWhere('ip_reporter = :ip_reporter')
->andWhere('doc_id = :doc_id')
// ->orWhere('media_id = :media_id')
->setParameters([
':board_id' => $report->board_id,
':doc_id' => $report->doc_id,
// ':media_id' => $report->media_id,
':ip_reporter' => $report->ip_reporter
])
->execute()
->fetch();
if ($submitted['count'] > 0) {
throw new ReportSubmitterBannedException(_i('You can only submit one report per post.'));
}
if ($ban = $this->ban_factory->isBanned($report->ip_reporter, $report->radix)) {
throw new ReportSubmitterBannedException($ban->getMessage());
}
return $report;
}
/**
* Adds a new report to the database
*
* @param \Foolz\FoolFuuka\Model\Radix $radix The Radix to which the Report is referred to
* @param int $id The ID of the object being reported (doc_id or media_id)
* @param string $reason The reason for the report
* @param string $ip_reporter The IP in decimal format
* @param string $mode The type of column (doc_id or media_id)
*
* @return \Foolz\FoolFuuka\Model\Report The created report
* @throws ReportMediaNotFoundException If the reported media_id doesn't exist
* @throws ReportCommentNotFoundException If the reported doc_id doesn't exist
* @throws ReportReasonTooLongException If the reason inserted was too long
* @throws ReportSentTooManyException If the user sent too many moderation in a timeframe
* @throws ReportReasonNullException If the report reason is null
* @throws ReportAlreadySubmittedException If the reporter’s IP has already submitted a report for the post.
* @throws ReportSubmitterBannedException If the reporter’s IP has been banned.
*/
public function p_add($radix, $id, $reason, $ip_reporter, $mode = 'doc_id')
{
if (trim($reason) === '') {
throw new ReportReasonNullException(_i('A reason must be included with your report.'));
}
if (mb_strlen($reason, 'utf-8') > 2048) {
throw new ReportReasonTooLongException(_i('The reason for you report was too long.'));
}
$report = new Report($this->getContext());
$report->radix = $radix;
$report->board_id = $radix->id;
$report->reason = $reason;
$report->ip_reporter = $ip_reporter;
switch ($mode) {
case 'media_id':
try {
$this->media_factory->getByMediaId($report->radix, $id);
$report->media_id = (int) $id;
} catch (MediaNotFoundException $e) {
throw new ReportMediaNotFoundException(_i('The media file you are reporting could not be found.'));
}
break;
default:
try {
Board::forge($this->getContext())
->getPost()
->setRadix($report->radix)
->setOptions('doc_id', $id)
->getComments();
$report->doc_id = (int) $id;
} catch (BoardException $e) {
throw new ReportCommentNotFoundException(_i('The post you are reporting could not be found.'));
}
}
$report = $this->validateUserReport($report);
$report->created = time();
$this->dc->getConnection()->insert($this->dc->p('reports'), [
'board_id' => $report->board_id,
'doc_id' => $report->doc_id,
'media_id' => $report->media_id,
'reason' => $report->reason,
'ip_reporter' => $report->ip_reporter,
'created' => $report->created,
]);
$this->clearCache();
return $report;
}
/**
* Deletes a Report
*
* @param int $id The ID of the Report
*
* @throws \Foolz\FoolFuuka\Model\ReportNotFoundException
*/
public function p_delete($id)
{
$this->dc->qb()
->delete($this->dc->p('reports'))
->where('id = :id')
->setParameter(':id', $id)
->execute();
$this->clearCache();
}
}