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 | |
3 | namespace MediaWiki\Extension\MediaModeration\Maintenance\Dev; |
4 | |
5 | use Error; |
6 | use LocalFile; |
7 | use Maintenance; |
8 | use MediaWiki\MediaWikiServices; |
9 | use MediaWiki\Title\Title; |
10 | use MediaWiki\User\User; |
11 | use 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' ); |
16 | if ( $IP === false ) { |
17 | $IP = __DIR__ . '/../../..'; |
18 | } |
19 | require_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 | */ |
26 | class 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; |
149 | require_once RUN_MAINTENANCE_IF_MAIN; |
150 | // @codeCoverageIgnoreEnd |