Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
PopulateImageTables
n/a
0 / 0
n/a
0 / 0
17
n/a
0 / 0
 __construct
n/a
0 / 0
n/a
0 / 0
1
 execute
n/a
0 / 0
n/a
0 / 0
13
 getImages
n/a
0 / 0
n/a
0 / 0
3
1<?php
2
3namespace MediaWiki\Extension\MediaModeration\Maintenance\Dev;
4
5use Error;
6use LocalFile;
7use Maintenance;
8use MediaWiki\MediaWikiServices;
9use MediaWiki\Title\Title;
10use MediaWiki\User\User;
11use UploadFromUrl;
12
13// This is a local development only script, no need to count it in code coverage metrics.
14// @codeCoverageIgnoreStart
15$IP = getenv( 'MW_INSTALL_PATH' );
16if ( $IP === false ) {
17    $IP = __DIR__ . '/../../..';
18}
19require_once "$IP/maintenance/Maintenance.php";
20
21/**
22 * Maintenance script for importing some real world images from Commons to a local wiki. A subset
23 * of the total will have new versions uploaded and another subset of the total will be deleted, so
24 * as to populate various tables that MediaModeration scans.
25 */
26class PopulateImageTables extends Maintenance {
27
28    public function __construct() {
29        parent::__construct();
30        $this->addDescription( 'Populate rows in image tables with fake data.
31        This cannot be easily undone. Do not run this script in production!' );
32        $this->addOption( 'count', 'How many rows to create' );
33    }
34
35    public function execute() {
36        if ( !$this->getConfig()->get( 'MediaModerationDeveloperMode' ) ||
37            !$this->getConfig()->get( 'AllowCopyUploads' ) ) {
38            $this->error( 'AllowCopyUploads and MediaModerationDeveloperMode must be set to true.' );
39            return;
40        }
41        if ( $this->getConfig()->get( 'MaxImageArea' ) ) {
42            $this->output( 'For this script, the recommended value for $wgMaxImageArea is `false`.' );
43        }
44        if ( $this->getConfig()->get( 'CheckFileExtensions' ) ) {
45            $this->output( 'For this script, the recommended value for $wgCheckFileExtensions is `false`.' );
46        }
47        $count = $this->getOption( 'count', 100 );
48        $user = User::newSystemUser( 'MediaModeration' );
49
50        // TODO: Allow for continuation if the user wants e.g. 1000 images imported.
51
52        $uploadedImages = [];
53        $fileRepo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
54
55        foreach ( $this->getImages( $count ) as $image ) {
56            $this->output( "Importing image {$image['title']}\n" );
57            $maintenanceUpload = new UploadFromUrl();
58            if ( !isset( $image['pageimage'] ) ) {
59                // TODO This occurs often. Should find some way to require that the metadata is present.
60                $this->output( "... skipping, does not have image metadata\n" );
61                continue;
62            }
63            $maintenanceUpload->initialize( $image['pageimage'], $image['original']['source'] );
64            if ( !$maintenanceUpload->getTitle() ) {
65                $this->fatalError( 'illegal-filename' );
66            }
67            $maintenanceUpload->fetchFile();
68            try {
69                $uploadResult = $maintenanceUpload->performUpload(
70                    'MediaModeration PopulateImageTables.php',
71                    'MediaModeration',
72                    false,
73                    $user
74                );
75                if ( $uploadResult->isGood() ) {
76                    $uploadedImages[] = $fileRepo->newFile(
77                        Title::newFromText( $image['title'], NS_FILE )
78                    );
79                } else {
80                    $this->error( "... unable to perform upload.\n" );
81                }
82            } catch ( Error $error ) {
83                $this->error( "... unable to import\n" );
84            }
85        }
86        // Upload new versions of 20% of images.
87        $newImageVersions = array_intersect_key( $uploadedImages, array_rand( $uploadedImages, $count / 5 ) );
88        // Get new images to use
89        $newImages = $this->getImages( $count / 5 );
90        /**
91         * @var int $key
92         * @var LocalFile $newImageVersion
93         */
94        foreach ( $newImageVersions as $key => $newImageVersion ) {
95            // Upload new version of image.
96            $maintenanceUpload = new UploadFromUrl();
97            $titleText = $newImageVersion->getTitle()->getText();
98            $maintenanceUpload->initialize( $titleText, $newImages[$key]['original']['source'] );
99            if ( !$maintenanceUpload->getTitle() ) {
100                $this->fatalError( 'illegal-filename' );
101            }
102            $maintenanceUpload->fetchFile();
103            $this->output( "Uploading new version of $titleText\n" );
104            $maintenanceUpload->performUpload(
105                'MediaModeration PopulateImages.php update',
106                'MediaModeration',
107                false,
108                $user
109            );
110        }
111        $deleteImages = array_intersect_key( $uploadedImages, array_rand( $uploadedImages, $count / 5 ) );
112        /** @var LocalFile $image */
113        foreach ( $deleteImages as $image ) {
114            $this->output( 'Deleting ' . $image->getTitle()->getText() . PHP_EOL );
115            $image->deleteFile( 'MediaModeration testing', $user );
116        }
117    }
118
119    private function getImages( int $count ): array {
120        $url = wfAppendQuery( 'https://commons.wikimedia.org/w/api.php', [
121            'action' => 'query',
122            'prop' => 'pageimages',
123            'generator' => 'search',
124            'piprop' => 'thumbnail|name|original',
125            'format' => 'json',
126            // Exclude items with .pdf
127            // TODO there's probably a nicer way to get just the file types we want.
128            'gsrsearch' => '!".pdf"',
129            'gsrnamespace' => NS_FILE,
130            'gsrsort' => 'random',
131            'gsrlimit' => $count,
132            'formatversion' => 2
133        ] );
134        $request = MediaWikiServices::getInstance()->getHttpRequestFactory()->create( $url );
135        $result = $request->execute();
136        if ( !$result->isOK() ) {
137            return [];
138        }
139        $data = json_decode( $request->getContent(), true );
140        if ( !isset( $data['query']['pages'] ) ) {
141            $this->error( 'Unable to get images' );
142            return [];
143        }
144        return $data['query']['pages'];
145    }
146}
147
148$maintClass = PopulateImageTables::class;
149require_once RUN_MAINTENANCE_IF_MAIN;
150// @codeCoverageIgnoreEnd