1
0
mirror of https://github.com/Intervention/image.git synced 2025-01-16 11:49:02 +01:00

Update code for phpstan level 6 (#1342)

* Update phpstan checks to level 6
* Add more details doc blocks to meet phpstan level 6
* Fix bug in building decoder chain
* Fix type hints
This commit is contained in:
Oliver Vogel 2024-05-02 11:03:18 +02:00 committed by GitHub
parent 449d074eba
commit 2dbfb53bf8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 205 additions and 56 deletions

View File

@ -1,5 +1,5 @@
parameters:
level: 5
level: 6
paths:
- src
exceptions:

View File

@ -10,8 +10,17 @@ use Countable;
use Traversable;
use IteratorAggregate;
/**
* @implements IteratorAggregate<int|string, mixed>
*/
class Collection implements CollectionInterface, IteratorAggregate, Countable
{
/**
* Create new collection object
*
* @param array<int|string, mixed> $items
* @return void
*/
public function __construct(protected array $items = [])
{
}
@ -19,14 +28,19 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
/**
* Static constructor
*
* @param array $items
* @return self
* @param array<int|string, mixed> $items
* @return self<int|string, mixed>
*/
public static function create(array $items = []): self
{
return new self($items);
}
/**
* {@inheritdoc}
*
* @see CollectionInterface::has()
*/
public function has(int|string $key): bool
{
return array_key_exists($key, $this->items);
@ -35,13 +49,18 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
/**
* Returns Iterator
*
* @return Traversable
* @return Traversable<int|string, mixed>
*/
public function getIterator(): Traversable
{
return new ArrayIterator($this->items);
}
/**
* {@inheritdoc}
*
* @see CollectionInterface::toArray()
*/
public function toArray(): array
{
return $this->items;
@ -61,7 +80,7 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
* Append new item to collection
*
* @param mixed $item
* @return CollectionInterface
* @return CollectionInterface<int|string, mixed>
*/
public function push($item): CollectionInterface
{
@ -154,6 +173,12 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
return $result;
}
/**
* Map each item of collection by given callback
*
* @param callable $callback
* @return self
*/
public function map(callable $callback): self
{
$items = array_map(function ($item) use ($callback) {
@ -167,7 +192,7 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
* Run callback on each item of the collection an remove it if it does not return true
*
* @param callable $callback
* @return Collection
* @return self
*/
public function filter(callable $callback): self
{

View File

@ -13,14 +13,26 @@ abstract class AbstractColor implements ColorInterface
{
/**
* Color channels
*
* @var array<ColorChannelInterface>
*/
protected array $channels;
/**
* {@inheritdoc}
*
* @see ColorInterface::channels()
*/
public function channels(): array
{
return $this->channels;
}
/**
* {@inheritdoc}
*
* @see ColorInterface::channel()
*/
public function channel(string $classname): ColorChannelInterface
{
$channels = array_filter($this->channels(), function (ColorChannelInterface $channel) use ($classname) {
@ -34,6 +46,11 @@ abstract class AbstractColor implements ColorInterface
return reset($channels);
}
/**
* {@inheritdoc}
*
* @see ColorInterface::normalize()
*/
public function normalize(): array
{
return array_map(function (ColorChannelInterface $channel) {

View File

@ -15,6 +15,11 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
class Colorspace implements ColorspaceInterface
{
/**
* Channel class names of colorspace
*
* @var array<string>
*/
public static array $channels = [
Channels\Cyan::class,
Channels\Magenta::class,

View File

@ -14,6 +14,11 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
class Colorspace implements ColorspaceInterface
{
/**
* Channel class names of colorspace
*
* @var array<string>
*/
public static array $channels = [
Channels\Hue::class,
Channels\Saturation::class,

View File

@ -14,6 +14,11 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
class Colorspace implements ColorspaceInterface
{
/**
* Channel class names of colorspace
*
* @var array<string>
*/
public static array $channels = [
Channels\Hue::class,
Channels\Saturation::class,

View File

@ -13,6 +13,11 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
class Colorspace implements ColorspaceInterface
{
/**
* Channel class names of colorspace
*
* @var array<string>
*/
public static array $channels = [
Channels\Red::class,
Channels\Green::class,

View File

@ -11,6 +11,11 @@ use Intervention\Image\Interfaces\ImageInterface;
class HtmlColornameDecoder extends HexColorDecoder implements DecoderInterface
{
/**
* Available color names and their corresponding hex codes
*
* @var array<string, string>
*/
protected static array $names = [
'lightsalmon' => '#ffa07a',
'salmon' => '#fa8072',

View File

@ -100,7 +100,7 @@ abstract class AbstractDecoder implements DecoderInterface
* data or a file path.
*
* @param string $path_or_data
* @return CollectionInterface
* @return CollectionInterface<string, mixed>
*/
protected function extractExifData(string $path_or_data): CollectionInterface
{
@ -156,9 +156,17 @@ abstract class AbstractDecoder implements DecoderInterface
return new class ($matches, $result)
{
/**
* @var array<mixed>
*/
private array $matches;
private int|false $result;
/**
* @param array<mixed> $matches
* @param int|false $result
* @return void
*/
public function __construct(array $matches, int|false $result)
{
$this->matches = $matches;

View File

@ -6,7 +6,6 @@ namespace Intervention\Image\Drivers;
use Intervention\Image\Exceptions\DriverException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\AnalyzerInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\DriverInterface;
@ -74,9 +73,6 @@ abstract class AbstractDriver implements DriverInterface
match (true) {
is_string($object) => new $object(),
is_object($object) => $object,
default => throw new RuntimeException(
'Specializable item must be either a class name or an object.'
)
}
);
}, $objects);

View File

@ -114,7 +114,7 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
* @param Line $line
* @param FontInterface $font
* @throws FontException
* @return array
* @return array<Line>
*/
protected function wrapLine(Line $line, FontInterface $font): array
{

View File

@ -6,13 +6,25 @@ namespace Intervention\Image\Drivers;
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\DecoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\InputHandlerInterface;
abstract class AbstractInputHandler implements InputHandlerInterface
{
/**
* Decoder classnames in hierarchical order
*
* @var array<string|DecoderInterface>
*/
protected array $decoders = [];
/**
* Create new input handler instance with given decoder classnames
*
* @param array<string|DecoderInterface> $decoders
* @return void
*/
public function __construct(array $decoders = [])
{
$this->decoders = count($decoders) ? $decoders : $this->decoders;
@ -40,13 +52,18 @@ abstract class AbstractInputHandler implements InputHandlerInterface
throw new DecoderException('No decoders found in ' . $this::class);
}
// get instance of last decoder in stack
list($classname) = array_slice(array_reverse($this->decoders), 0, 1);
$chain = new $classname();
// get last decoder in stack
list($decoder) = array_slice(array_reverse($this->decoders), 0, 1);
$chain = ($decoder instanceof DecoderInterface) ? $decoder : new $decoder();
// only accept DecoderInterface
if (!($chain instanceof DecoderInterface)) {
throw new DecoderException('Decoder must implement in ' . DecoderInterface::class);
}
// build decoder chain
foreach (array_slice(array_reverse($this->decoders), 1) as $classname) {
$chain = new $classname($chain);
foreach (array_slice(array_reverse($this->decoders), 1) as $decoder) {
$chain = ($decoder instanceof DecoderInterface) ? new ($decoder::class)($chain) : new $decoder($chain);
}
return $chain;

View File

@ -87,7 +87,7 @@ class Driver extends AbstractDriver
/**
* @throws RuntimeException
*/
public function add($source, float $delay = 1): self
public function add(mixed $source, float $delay = 1): self
{
$this->core->add(
$this->driver->handleInput($source)->core()->first()->setDelay($delay)

View File

@ -24,6 +24,11 @@ use Intervention\Image\Drivers\Gd\Decoders\SplFileInfoImageDecoder;
class InputHandler extends AbstractInputHandler
{
/**
* Decoders in hierarchical order
*
* @var array<string>
*/
protected array $decoders = [
NativeObjectDecoder::class,
ImageObjectDecoder::class,

View File

@ -4,8 +4,8 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Gd\Modifiers;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\FillModifier as GenericFillModifier;
@ -37,7 +37,7 @@ class FillModifier extends GenericFillModifier implements SpecializedInterface
);
}
private function floodFillWithColor(Frame $frame, int $color): void
private function floodFillWithColor(FrameInterface $frame, int $color): void
{
imagefill(
$frame->native(),
@ -47,7 +47,7 @@ class FillModifier extends GenericFillModifier implements SpecializedInterface
);
}
private function fillAllWithColor(Frame $frame, int $color): void
private function fillAllWithColor(FrameInterface $frame, int $color): void
{
imagealphablending($frame->native(), true);
imagefilledrectangle(

View File

@ -20,6 +20,11 @@ class SharpenModifier extends GenericSharpenModifier implements SpecializedInter
return $image;
}
/**
* Create matrix to be used by imageconvolution()
*
* @return array<array<float>>
*/
private function matrix(): array
{
$min = $this->amount >= 10 ? $this->amount * -0.01 : 0;

View File

@ -12,6 +12,9 @@ use Intervention\Image\Exceptions\AnimationException;
use Intervention\Image\Interfaces\CollectionInterface;
use Intervention\Image\Interfaces\FrameInterface;
/**
* @implements Iterator<FrameInterface>
*/
class Core implements CoreInterface, Iterator
{
protected int $iteratorIndex = 0;

View File

@ -89,7 +89,7 @@ class Driver extends AbstractDriver
/**
* @throws RuntimeException
*/
public function add($source, float $delay = 1): self
public function add(mixed $source, float $delay = 1): self
{
$native = $this->driver->handleInput($source)->core()->native();
$native->setImageDelay(intval(round($delay * 100)));

View File

@ -24,6 +24,11 @@ use Intervention\Image\Drivers\Imagick\Decoders\SplFileInfoImageDecoder;
class InputHandler extends AbstractInputHandler
{
/**
* Decoders in hierarchical order
*
* @var array<string>
*/
protected array $decoders = [
NativeObjectDecoder::class,
ImageObjectDecoder::class,

View File

@ -15,6 +15,11 @@ use Intervention\Image\Modifiers\ColorspaceModifier as GenericColorspaceModifier
class ColorspaceModifier extends GenericColorspaceModifier implements SpecializedInterface
{
/**
* Map own colorspace classname to Imagick classnames
*
* @var array<string, int>
*/
protected static array $mapping = [
RgbColorspace::class => Imagick::COLORSPACE_SRGB,
CmykColorspace::class => Imagick::COLORSPACE_CMYK,

View File

@ -45,6 +45,11 @@ class DrawPolygonModifier extends GenericDrawPolygonModifier implements Speciali
return $image;
}
/**
* Return points of drawable in processable form for ImagickDraw
*
* @return array<array<string, int>>
*/
private function points(): array
{
$points = [];

View File

@ -7,7 +7,7 @@ namespace Intervention\Image\Drivers\Imagick\Modifiers;
use Imagick;
use ImagickDraw;
use ImagickPixel;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\FillModifier as ModifiersFillModifier;
@ -32,7 +32,7 @@ class FillModifier extends ModifiersFillModifier implements SpecializedInterface
return $image;
}
private function floodFillWithColor(Frame $frame, ImagickPixel $pixel): void
private function floodFillWithColor(FrameInterface $frame, ImagickPixel $pixel): void
{
$target = $frame->native()->getImagePixelColor(
$this->position->x(),
@ -50,7 +50,7 @@ class FillModifier extends ModifiersFillModifier implements SpecializedInterface
);
}
private function fillAllWithColor(Frame $frame, ImagickPixel $pixel): void
private function fillAllWithColor(FrameInterface $frame, ImagickPixel $pixel): void
{
$draw = new ImagickDraw();
$draw->setFillColor($pixel);

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Imagick\Modifiers;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\PixelateModifier as GenericPixelateModifier;
@ -20,7 +20,7 @@ class PixelateModifier extends GenericPixelateModifier implements SpecializedInt
return $image;
}
protected function pixelateFrame(Frame $frame): void
protected function pixelateFrame(FrameInterface $frame): void
{
$size = $frame->size();

View File

@ -8,12 +8,12 @@ use ImagickDraw;
use ImagickDrawException;
use ImagickException;
use Intervention\Image\Drivers\Imagick\FontProcessor;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Exceptions\FontException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Geometry\Point;
use Intervention\Image\Interfaces\FontInterface;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\TextModifier as GenericTextModifier;
@ -109,14 +109,14 @@ class TextModifier extends GenericTextModifier implements SpecializedInterface
* Maybe draw given line of text on frame instance depending on given
* ImageDraw instance. Optionally move line position by given offset.
*
* @param Frame $frame
* @param FrameInterface $frame
* @param Line $textline
* @param null|ImagickDraw $draw
* @param Point $offset
* @return void
*/
private function maybeDrawTextline(
Frame $frame,
FrameInterface $frame,
Line $textline,
?ImagickDraw $draw = null,
Point $offset = new Point(),

View File

@ -13,6 +13,11 @@ use Intervention\Image\Interfaces\ImageInterface;
class FileExtensionEncoder extends AutoEncoder
{
/**
* Encoder options
*
* @var array<string, mixed>
*/
protected array $options = [];
/**

View File

@ -14,6 +14,11 @@ use Intervention\Image\MediaType;
class MediaTypeEncoder extends AbstractEncoder
{
/**
* Encoder options
*
* @var array<string, mixed>
*/
protected array $options = [];
/**

View File

@ -67,7 +67,7 @@ enum Format
/**
* Return the possible media (MIME) types for the current format
*
* @return array
* @return array<MediaType>
*/
public function mediaTypes(): array
{
@ -79,7 +79,7 @@ enum Format
/**
* Return the possible file extension for the current format
*
* @return array
* @return array<FileExtension>
*/
public function fileExtensions(): array
{

View File

@ -14,6 +14,10 @@ use Intervention\Image\Geometry\Traits\HasBorder;
use Intervention\Image\Interfaces\DrawableInterface;
use Intervention\Image\Interfaces\PointInterface;
/**
* @implements IteratorAggregate<Point>
* @implements ArrayAccess<int, Point>
*/
class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInterface
{
use HasBorder;
@ -22,7 +26,7 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
/**
* Create new polygon instance
*
* @param array $points
* @param array<Point> $points
* @param PointInterface $pivot
* @return void
*/
@ -45,7 +49,7 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
/**
* Implement iteration through all points of polygon
*
* @return Traversable
* @return Traversable<Point>
*/
public function getIterator(): Traversable
{
@ -427,7 +431,7 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
/**
* Return array of all x/y values of all points of polygon
*
* @return array
* @return array<int>
*/
public function toArray(): array
{

View File

@ -44,6 +44,7 @@ use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\FontInterface;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ModifierInterface;
use Intervention\Image\Interfaces\ProfileInterface;
@ -183,7 +184,7 @@ final class Image implements ImageInterface
/**
* Implementation of IteratorAggregate
*
* @return Traversable
* @return Traversable<FrameInterface>
*/
public function getIterator(): Traversable
{

View File

@ -6,6 +6,9 @@ namespace Intervention\Image\Interfaces;
use Traversable;
/**
* @extends Traversable<int|string, mixed>
*/
interface CollectionInterface extends Traversable
{
/**
@ -20,7 +23,7 @@ interface CollectionInterface extends Traversable
* Add item to collection
*
* @param mixed $item
* @return CollectionInterface
* @return CollectionInterface<int|string, mixed>
*/
public function push($item): self;
@ -66,14 +69,14 @@ interface CollectionInterface extends Traversable
/**
* Empty collection
*
* @return CollectionInterface
* @return CollectionInterface<int|string, mixed>
*/
public function empty(): self;
/**
* Transform collection as array
*
* @return array
* @return array<int|string, mixed>
*/
public function toArray(): array;
@ -82,7 +85,7 @@ interface CollectionInterface extends Traversable
*
* @param int $offset
* @param null|int $length
* @return CollectionInterface
* @return CollectionInterface<int|string, mixed>
*/
public function slice(int $offset, ?int $length = 0): self;
}

View File

@ -43,7 +43,7 @@ interface ColorInterface
/**
* Cast color object to array
*
* @return array
* @return array<int>
*/
public function toArray(): array;
@ -57,10 +57,17 @@ interface ColorInterface
/**
* Return array of all color channels
*
* @return array
* @return array<ColorChannelInterface>
*/
public function channels(): array;
/**
* Return array of normalized color channel values
*
* @return array<float>
*/
public function normalize(): array;
/**
* Retrieve the color channel by its classname
*

View File

@ -17,7 +17,7 @@ interface ColorspaceInterface
/**
* Create new color in colorspace from given normalized channel values
*
* @param array $normalized
* @param array<float> $normalized
* @return ColorInterface
*/
public function colorFromNormalized(array $normalized): ColorInterface;

View File

@ -20,7 +20,7 @@ interface CoreInterface extends CollectionInterface
* Set driver's representation of the image core.
*
* @param mixed $native
* @return CoreInterface
* @return CoreInterface<FrameInterface>
*/
public function setNative(mixed $native): self;
@ -44,7 +44,7 @@ interface CoreInterface extends CollectionInterface
* Add new frame to core
*
* @param FrameInterface $frame
* @return CoreInterface
* @return CoreInterface<FrameInterface>
*/
public function add(FrameInterface $frame): self;
@ -60,7 +60,7 @@ interface CoreInterface extends CollectionInterface
* value of 0 means infinite repetition.
*
* @param int $loops
* @return CoreInterface
* @return CoreInterface<FrameInterface>
*/
public function setLoops(int $loops): self;

View File

@ -34,8 +34,8 @@ interface DriverInterface
/**
* Resolve array of classnames or objects into their specialized version for the current driver
*
* @param array $objects
* @return array
* @param array<string|object> $objects
* @return array<object>
*/
public function specializeMultiple(array $objects): array;
@ -61,7 +61,7 @@ interface DriverInterface
* Handle given input by decoding it to ImageInterface or ColorInterface
*
* @param mixed $input
* @param array $decoders
* @param array<string|DecoderInterface> $decoders
* @throws RuntimeException
* @return ImageInterface|ColorInterface
*/

View File

@ -13,6 +13,9 @@ use Intervention\Image\MediaType;
use Intervention\Image\Origin;
use IteratorAggregate;
/**
* @extends IteratorAggregate<FrameInterface>
*/
interface ImageInterface extends IteratorAggregate, Countable
{
/**

View File

@ -44,7 +44,7 @@ interface ImageManagerInterface
*
* @link https://image.intervention.io/v3/basics/instantiation#reading-images
* @param mixed $input
* @param string|array|DecoderInterface $decoders
* @param string|array<DecoderInterface>|DecoderInterface $decoders
* @throws RuntimeException
* @return ImageInterface
*/

View File

@ -10,7 +10,7 @@ interface SpecializableInterface
* Return an array of constructor parameters, which is usually passed from
* the generic object to the specialized object
*
* @return array
* @return array<string, mixed>
*/
public function specializable(): array;

View File

@ -12,7 +12,7 @@ class ModifierStack implements ModifierInterface
/**
* Create new modifier stack object with an array of modifier objects
*
* @param array $modifiers
* @param array<ModifierInterface> $modifiers
* @return void
*/
public function __construct(protected array $modifiers)

View File

@ -69,7 +69,7 @@ class TextModifier extends SpecializableModifier
* Return array of offset points to draw text stroke effect below the actual text
*
* @param FontInterface $font
* @return array
* @return array<Point>
*/
protected function strokeOffsets(FontInterface $font): array
{

View File

@ -11,10 +11,15 @@ use Intervention\Image\Interfaces\PointInterface;
use IteratorAggregate;
use Traversable;
/**
* @implements IteratorAggregate<string>
*/
class Line implements IteratorAggregate, Countable
{
/**
* Segments (usually individual words including punctuation marks) of the line
*
* @var array<string>
*/
protected array $segments = [];
@ -50,7 +55,7 @@ class Line implements IteratorAggregate, Countable
/**
* Returns Iterator
*
* @return Traversable
* @return Traversable<string>
*/
public function getIterator(): Traversable
{

View File

@ -18,7 +18,7 @@ class TextBlock extends Collection
/**
* Return array of lines in text block
*
* @return array
* @return array<Line>
*/
public function lines(): array
{
@ -28,7 +28,7 @@ class TextBlock extends Collection
/**
* Set lines of the text block
*
* @param array $lines
* @param array<Line> $lines
* @return self
*/
public function setLines(array $lines): self