I believe we don't need this any more. A test should never leave an uploaded image behind, but delete it. It should be totally fine when the same trivial test uploads the same image over and over again. All the extra complexity to trick MediaWiki's duplicate detection shouldn't be necessary (any more). Also change the default to svg instead of jpg. Again, this creates much smaller files with much less effort. Note this code was already mostly unused because of the previous patch I7f3d586. Change-Id: I5c16ba7bed0fffa43549b786e50d6d1dd5592ad0
200 lines
6.1 KiB
PHP
200 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Tests\Api;
|
|
|
|
/**
|
|
* RandomImageGenerator -- does what it says on the tin.
|
|
* Requires Imagick, the ImageMagick library for PHP, or the command line
|
|
* equivalent (usually 'convert').
|
|
*
|
|
* @file
|
|
* @author Neil Kandalgaonkar <neilk@wikimedia.org>
|
|
*/
|
|
|
|
use Exception;
|
|
use Imagick;
|
|
use ImagickPixel;
|
|
use MediaWiki\Shell\Shell;
|
|
use SimpleXMLElement;
|
|
use UnexpectedValueException;
|
|
|
|
/**
|
|
* RandomImageGenerator: does what it says on the tin.
|
|
* Can fetch a random image, or also write a number of them to disk with random filenames.
|
|
*/
|
|
class RandomImageGenerator {
|
|
private $minWidth = 16;
|
|
private $maxWidth = 16;
|
|
private $minHeight = 16;
|
|
private $maxHeight = 16;
|
|
|
|
public function __construct( $options = [] ) {
|
|
foreach ( [ 'minWidth', 'minHeight',
|
|
'maxWidth', 'maxHeight' ] as $property
|
|
) {
|
|
if ( isset( $options[$property] ) ) {
|
|
$this->$property = $options[$property];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes random images with random filenames to disk in the directory you
|
|
* specify, or current working directory.
|
|
*
|
|
* @param int $number Number of filenames to write
|
|
* @param string $format Optional, must be understood by ImageMagick, such as 'jpg' or 'gif'
|
|
* @param string|null $dir Directory, optional (will default to current working directory)
|
|
* @return array Filenames we just wrote
|
|
*/
|
|
public function writeImages( $number, $format = 'svg', $dir = null ) {
|
|
$filenames = $this->getRandomFilenames( $number, $format, $dir );
|
|
$imageWriteMethod = $this->getImageWriteMethod( $format );
|
|
foreach ( $filenames as $filename ) {
|
|
$this->{$imageWriteMethod}( $this->getImageSpec(), $format, $filename );
|
|
}
|
|
|
|
return $filenames;
|
|
}
|
|
|
|
/**
|
|
* Figure out how we write images. This is a factor of both format and the local system
|
|
*
|
|
* @param string $format (a typical extension like 'svg', 'jpg', etc.)
|
|
*
|
|
* @throws Exception
|
|
* @return string
|
|
*/
|
|
public function getImageWriteMethod( $format ) {
|
|
global $wgUseImageMagick, $wgImageMagickConvertCommand;
|
|
if ( $format === 'svg' ) {
|
|
return 'writeSvg';
|
|
} else {
|
|
// figure out how to write images
|
|
global $wgExiv2Command;
|
|
if ( class_exists( Imagick::class ) && $wgExiv2Command && is_executable( $wgExiv2Command ) ) {
|
|
return 'writeImageWithApi';
|
|
} elseif ( $wgUseImageMagick
|
|
&& $wgImageMagickConvertCommand
|
|
&& is_executable( $wgImageMagickConvertCommand )
|
|
) {
|
|
return 'writeImageWithCommandLine';
|
|
}
|
|
}
|
|
throw new Exception( "RandomImageGenerator: could not find a suitable "
|
|
. "method to write images in '$format' format" );
|
|
}
|
|
|
|
/**
|
|
* Return a number of randomly-generated filenames.
|
|
*
|
|
* Each filename uses follows the pattern "hex_timestamp_1.jpg".
|
|
*
|
|
* @param int $number Number of filenames to generate
|
|
* @param string $extension
|
|
* @param string|null $dir Optional, defaults to current working directory
|
|
* @return string[]
|
|
*/
|
|
private function getRandomFilenames( $number, $extension = 'svg', $dir = null ) {
|
|
$dir ??= getcwd();
|
|
$filenames = [];
|
|
$prefix = wfRandomString( 3 ) . '_' . gmdate( 'YmdHis' ) . '_';
|
|
foreach ( range( 1, $number ) as $offset ) {
|
|
$filename = $prefix . $offset;
|
|
if ( $extension !== null ) {
|
|
$filename .= '.' . $extension;
|
|
}
|
|
$filenames[] = "$dir/$filename";
|
|
}
|
|
|
|
return $filenames;
|
|
}
|
|
|
|
/**
|
|
* Generate data representing an image of random size (within limits),
|
|
* consisting of randomly colored and sized upward pointing triangles
|
|
* against a random background color. (This data is used in the
|
|
* writeImage* methods).
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getImageSpec() {
|
|
return [
|
|
'width' => mt_rand( $this->minWidth, $this->maxWidth ),
|
|
'height' => mt_rand( $this->minHeight, $this->maxHeight ),
|
|
'fill' => '#f0f',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Based on image specification, write a very simple SVG file to disk.
|
|
* Ignores the background spec because transparency is cool. :)
|
|
*
|
|
* @param array $spec Spec describing background and shapes to draw
|
|
* @param string $format File format to write (which is obviously always svg here)
|
|
* @param string $filename Filename to write to
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
public function writeSvg( $spec, $format, $filename ) {
|
|
$svg = new SimpleXmlElement( '<svg/>' );
|
|
$svg->addAttribute( 'xmlns', 'http://www.w3.org/2000/svg' );
|
|
$svg->addAttribute( 'width', $spec['width'] );
|
|
$svg->addAttribute( 'height', $spec['height'] );
|
|
|
|
$fh = fopen( $filename, 'w' );
|
|
if ( !$fh ) {
|
|
throw new UnexpectedValueException( "couldn't open $filename for writing" );
|
|
}
|
|
fwrite( $fh, $svg->asXML() );
|
|
if ( !fclose( $fh ) ) {
|
|
throw new UnexpectedValueException( "couldn't close $filename" );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Based on an image specification, write such an image to disk, using Imagick PHP extension
|
|
* @param array $spec Spec describing background and circles to draw
|
|
* @param string $format File format to write
|
|
* @param string $filename Filename to write to
|
|
*/
|
|
public function writeImageWithApi( $spec, $format, $filename ) {
|
|
$image = new Imagick();
|
|
$image->newImage( $spec['width'], $spec['height'], new ImagickPixel( $spec['fill'] ) );
|
|
$image->setImageFormat( $format );
|
|
$image->writeImage( $filename );
|
|
}
|
|
|
|
/**
|
|
* Based on an image specification, write such an image to disk, using the
|
|
* command line ImageMagick program ('convert').
|
|
*
|
|
* Sample command line:
|
|
* $ convert -size 100x60 xc:rgb(90,87,45) \
|
|
* -draw 'fill rgb(12,34,56) polygon 41,39 44,57 50,57 41,39' \
|
|
* -draw 'fill rgb(99,123,231) circle 59,39 56,57' \
|
|
* -draw 'fill rgb(240,12,32) circle 50,21 50,3' filename.png
|
|
*
|
|
* @param array $spec Spec describing background and shapes to draw
|
|
* @param string $format File format to write (unused by this method but
|
|
* kept so it has the same signature as writeImageWithApi).
|
|
* @param string $filename Filename to write to
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function writeImageWithCommandLine( $spec, $format, $filename ) {
|
|
global $wgImageMagickConvertCommand;
|
|
|
|
$args = [
|
|
$wgImageMagickConvertCommand,
|
|
'-size',
|
|
$spec['width'] . 'x' . $spec['height'],
|
|
"xc:{$spec['fill']}",
|
|
$filename,
|
|
];
|
|
Shell::command( $args )->execute();
|
|
}
|
|
|
|
}
|
|
|
|
class_alias( RandomImageGenerator::class, 'RandomImageGenerator' );
|