Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
24 / 24 |
|
100.00% |
5 / 5 |
CRAP | |
100.00% |
1 / 1 |
MediaModerationDatabaseManager | |
100.00% |
24 / 24 |
|
100.00% |
5 / 5 |
7 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
insertFileToScanTable | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
insertToScanTableInternal | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
updateMatchStatus | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
updateMatchStatusForSha1 | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\MediaModeration\Services; |
4 | |
5 | use ArchivedFile; |
6 | use File; |
7 | use IDBAccessObject; |
8 | use Wikimedia\Rdbms\IDatabase; |
9 | use Wikimedia\Timestamp\ConvertibleTimestamp; |
10 | |
11 | class MediaModerationDatabaseManager { |
12 | |
13 | private IDatabase $dbw; |
14 | private MediaModerationDatabaseLookup $mediaModerationDatabaseLookup; |
15 | |
16 | public function __construct( |
17 | IDatabase $dbw, |
18 | MediaModerationDatabaseLookup $mediaModerationDatabaseLookup |
19 | ) { |
20 | $this->dbw = $dbw; |
21 | $this->mediaModerationDatabaseLookup = $mediaModerationDatabaseLookup; |
22 | } |
23 | |
24 | /** |
25 | * Takes a File object and adds a reference to the file in the |
26 | * mediamoderation_scan table if the reference to the file does |
27 | * not already exist. |
28 | * |
29 | * @param File|ArchivedFile $file The file to be added to the mediamoderation_scan table. |
30 | * @return void |
31 | */ |
32 | public function insertFileToScanTable( $file ) { |
33 | if ( !$this->mediaModerationDatabaseLookup->fileExistsInScanTable( |
34 | $file, IDBAccessObject::READ_LATEST |
35 | ) ) { |
36 | $this->insertToScanTableInternal( $file ); |
37 | } |
38 | } |
39 | |
40 | /** |
41 | * Inserts a given File to the mediamoderation_scan table. |
42 | * Does not check for the existence of the File in the scan |
43 | * table, so will cause a DBError if the File is already in |
44 | * the table. |
45 | * |
46 | * @param File|ArchivedFile $file |
47 | * @return void |
48 | */ |
49 | private function insertToScanTableInternal( $file ) { |
50 | // Insert a row to the mediamoderation_scan table with the SHA-1 of the file. |
51 | $this->dbw->newInsertQueryBuilder() |
52 | ->insert( 'mediamoderation_scan' ) |
53 | ->row( [ 'mms_sha1' => $file->getSha1() ] ) |
54 | ->caller( __METHOD__ ) |
55 | ->execute(); |
56 | } |
57 | |
58 | /** |
59 | * Updates the mediamoderation_scan row with for the given file |
60 | * with the match status as determined by PhotoDNA. |
61 | * |
62 | * This also sets the mss_last_checked column to the current time |
63 | * to indicate that now is the last time the file was checked. |
64 | * |
65 | * If the SHA-1 of the $file does not exist in the scan table, a row |
66 | * will be created for it before the update occurs. |
67 | * |
68 | * @param File|ArchivedFile $file The file that was scanned by PhotoDNA |
69 | * @param null|bool $isMatch Whether the file is a match (null if the scan failed) |
70 | * @return void |
71 | */ |
72 | public function updateMatchStatus( $file, ?bool $isMatch ) { |
73 | // Check if the SHA-1 exists in the scan table. If not, then add it to the |
74 | // mediamoderation_scan table first before attempting to update the match status. |
75 | $this->insertFileToScanTable( $file ); |
76 | $this->updateMatchStatusForSha1( $file->getSha1(), $isMatch ); |
77 | } |
78 | |
79 | /** |
80 | * Updates the mediamoderation_scan row for the given SHA-1 |
81 | * with the match status as determined by PhotoDNA. |
82 | * |
83 | * If you have a $file object, you should pass use ::updateMatchStatus |
84 | * instead as this method does not first check if the file is referenced |
85 | * in the mediamoderation_scan table. |
86 | * |
87 | * @param string $sha1 |
88 | * @param null|bool $isMatch Whether the file is a match (null if the scan failed) |
89 | * @return void |
90 | */ |
91 | public function updateMatchStatusForSha1( string $sha1, ?bool $isMatch ) { |
92 | // If $isMatch is a boolean, convert this to the string representation of a boolean |
93 | // for storage in the DB. |
94 | if ( $isMatch !== null ) { |
95 | $isMatch = intval( $isMatch ); |
96 | } |
97 | // Update the match status for the $sha1 and also update the last checked timestamp. |
98 | $this->dbw->newUpdateQueryBuilder() |
99 | ->table( 'mediamoderation_scan' ) |
100 | ->set( [ |
101 | 'mms_is_match' => $isMatch, |
102 | // Take the MW_TS current timestamp and keep the first 8 characters which is YYYYMMDD. |
103 | 'mms_last_checked' => intval( substr( ConvertibleTimestamp::now(), 0, 8 ) ) |
104 | ] ) |
105 | ->where( [ 'mms_sha1' => $sha1 ] ) |
106 | ->caller( __METHOD__ ) |
107 | ->execute(); |
108 | } |
109 | } |