Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
DebugPhotoDNA
n/a
0 / 0
n/a
0 / 0
13
n/a
0 / 0
 __construct
n/a
0 / 0
n/a
0 / 0
1
 execute
n/a
0 / 0
n/a
0 / 0
12
1<?php
2
3namespace MediaWiki\Extension\MediaModeration\Maintenance;
4
5use MediaWiki\Context\RequestContext;
6use MediaWiki\Extension\MediaModeration\PhotoDNA\Response;
7use MediaWiki\Extension\MediaModeration\Services\MediaModerationPhotoDNAServiceProvider;
8use MediaWiki\Json\FormatJson;
9use MediaWiki\Maintenance\Maintenance;
10use MediaWiki\Title\Title;
11
12// This is a developer script, no need to count it in code coverage metrics.
13// @codeCoverageIgnoreStart
14$IP = getenv( 'MW_INSTALL_PATH' );
15if ( $IP === false ) {
16    $IP = __DIR__ . '/../../..';
17}
18require_once "$IP/maintenance/Maintenance.php";
19
20/**
21 * Helper script to check how the result from transmitting a local file
22 * via the service provider implementation to PhotoDNA. Does not have
23 * any side effects in the mediamoderation_scan table.
24 */
25class DebugPhotoDNA extends Maintenance {
26
27    public function __construct() {
28        parent::__construct();
29        $this->requireExtension( 'MediaModeration' );
30
31        $this->addDescription( 'Debug sending a single file to the PhotoDNA service endpoint via MediaModeration.' );
32        $this->addArg( 'filename', 'Filename (without File: prefix) to use in check.' );
33        $this->addOption( 'use-mock-endpoint', 'Use the mock API endpoint. Default is false, and to use production.' );
34        $this->addOption( 'raw-json', 'Return only the raw JSON from the endpoint, useful if you want to pipe to jq' );
35    }
36
37    public function execute() {
38        $services = $this->getServiceContainer();
39        $useMock = $this->getOption( 'use-mock-endpoint', false );
40        $photoDNAServiceProvider = $useMock ?
41                $services->get( '_MediaModerationMockPhotoDNAServiceProvider' ) :
42                $services->get( 'MediaModerationPhotoDNAServiceProvider' );
43        if ( !$useMock && !( $photoDNAServiceProvider instanceof MediaModerationPhotoDNAServiceProvider ) ) {
44            $this->fatalError(
45                'Unable to get production service provider. ' .
46                 'Check that $wgMediaModerationPhotoDNAUrl and $wgMediaModerationPhotoDNASubscriptionKey are set.'
47            );
48        }
49        $file = $services->getRepoGroup()->getLocalRepo()->findFile(
50            Title::newFromText( $this->getArg(), NS_FILE )
51        );
52        if ( !$file ) {
53            $this->fatalError( 'Unable to get file for ' . $this->getArg() );
54        }
55        $result = $photoDNAServiceProvider->check( $file );
56        /** @var Response|null $response */
57        $response = $result->getValue();
58        $statusFormatter = $services->getFormatterFactory()->getStatusFormatter( RequestContext::getMain() );
59
60        if ( $this->getOption( 'raw-json' ) ) {
61            if ( !$response ) {
62                $this->fatalError( FormatJson::encode( [ 'error' => $statusFormatter->getWikiText( $result ) ] ) );
63            }
64            $this->output( $response->getRawResponse() );
65            return;
66        }
67
68        $this->output( 'StatusValue: ' . ( $result->isGood() ? 'good' : 'bad' ) . PHP_EOL );
69        if ( $response ) {
70            $this->output( 'Status code: ' . $response->getStatusCode() . PHP_EOL );
71        }
72        if ( $result->isGood() && $response ) {
73            $this->output( 'IsMatch: ' . (int)$response->isMatch() . PHP_EOL );
74        } else {
75            $this->output(
76                'Error: ' . $statusFormatter->getWikiText( $result ) . PHP_EOL
77            );
78        }
79        if ( $response ) {
80            $this->output( 'Raw response: ' . PHP_EOL . $response->getRawResponse() . PHP_EOL );
81        }
82    }
83}
84
85$maintClass = DebugPhotoDNA::class;
86require_once RUN_MAINTENANCE_IF_MAIN;
87// @codeCoverageIgnoreEnd