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

Feature/code modernization (#1412)

* Update phpstan dependency version
* Remove unused code
* Optimize code
* Add type hints
* Change property visibility on final classes
* Modernize code
This commit is contained in:
Oliver Vogel 2025-01-05 10:43:14 +01:00 committed by GitHub
parent 3374d75384
commit c837fc9ffe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 108 additions and 123 deletions

View File

@ -26,7 +26,7 @@
"require-dev": {
"phpunit/phpunit": "^10.0 || ^11.0",
"mockery/mockery": "^1.6",
"phpstan/phpstan": "^2",
"phpstan/phpstan": "^2.1",
"squizlabs/php_codesniffer": "^3.8",
"slevomat/coding-standard": "~8.0"
},

View File

@ -153,7 +153,7 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
return $this->items[$query];
}
if (is_string($query) && strpos($query, '.') === false) {
if (is_string($query) && !str_contains($query, '.')) {
return array_key_exists($query, $this->items) ? $this->items[$query] : $default;
}

View File

@ -9,8 +9,9 @@ use Intervention\Image\Interfaces\ColorChannelInterface;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorspaceInterface;
use ReflectionClass;
use Stringable;
abstract class AbstractColor implements ColorInterface
abstract class AbstractColor implements ColorInterface, Stringable
{
/**
* Color channels
@ -38,7 +39,7 @@ abstract class AbstractColor implements ColorInterface
{
$channels = array_filter(
$this->channels(),
fn(ColorChannelInterface $channel) => $channel::class == $classname,
fn(ColorChannelInterface $channel): bool => $channel::class === $classname,
);
if (count($channels) == 0) {
@ -56,7 +57,7 @@ abstract class AbstractColor implements ColorInterface
public function normalize(): array
{
return array_map(
fn(ColorChannelInterface $channel) => $channel->normalize(),
fn(ColorChannelInterface $channel): float => $channel->normalize(),
$this->channels(),
);
}
@ -69,7 +70,7 @@ abstract class AbstractColor implements ColorInterface
public function toArray(): array
{
return array_map(
fn(ColorChannelInterface $channel) => $channel->value(),
fn(ColorChannelInterface $channel): int => $channel->value(),
$this->channels()
);
}

View File

@ -6,8 +6,9 @@ namespace Intervention\Image\Colors;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Interfaces\ColorChannelInterface;
use Stringable;
abstract class AbstractColorChannel implements ColorChannelInterface
abstract class AbstractColorChannel implements ColorChannelInterface, Stringable
{
protected int $value;

View File

@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input');
}
$values = array_map(function ($value) {
$values = array_map(function (string $value): int {
return intval(round(floatval(trim(str_replace('%', '', $value)))));
}, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]);

View File

@ -68,7 +68,7 @@ class Colorspace implements ColorspaceInterface
// normalized values of rgb channels
$values = array_map(
fn(ColorChannelInterface $channel) => $channel->normalize(),
fn(ColorChannelInterface $channel): float => $channel->normalize(),
$color->channels(),
);
@ -88,7 +88,7 @@ class Colorspace implements ColorspaceInterface
};
// calculate hue
list($r, $g, $b) = $values;
[$r, $g, $b] = $values;
$hue = match (true) {
($delta == 0) => 0,
($max == $r) => 60 * fmod((($g - $b) / $delta), 6),
@ -118,8 +118,8 @@ class Colorspace implements ColorspaceInterface
}
// normalized values of hsv channels
list($h, $s, $v) = array_map(
fn(ColorChannelInterface $channel) => $channel->normalize(),
[$h, $s, $v] = array_map(
fn(ColorChannelInterface $channel): float => $channel->normalize(),
$color->channels(),
);

View File

@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input');
}
$values = array_map(function ($value) {
$values = array_map(function (string $value): int {
return match (strpos($value, '%')) {
false => intval(trim($value)),
default => intval(trim(str_replace('%', '', $value))),

View File

@ -67,7 +67,7 @@ class Colorspace implements ColorspaceInterface
}
// normalized values of rgb channels
$values = array_map(fn(ColorChannelInterface $channel) => $channel->normalize(), $color->channels());
$values = array_map(fn(ColorChannelInterface $channel): float => $channel->normalize(), $color->channels());
// take only RGB
$values = array_slice($values, 0, 3);
@ -89,7 +89,7 @@ class Colorspace implements ColorspaceInterface
$s = 100 * ($chroma / $max);
// calculate hue
list($r, $g, $b) = $values;
[$r, $g, $b] = $values;
$h = match (true) {
($r == $min) => 3 - (($g - $b) / $chroma),
($b == $min) => 1 - (($r - $g) / $chroma),
@ -115,7 +115,10 @@ class Colorspace implements ColorspaceInterface
}
// normalized values of hsl channels
list($h, $s, $l) = array_map(fn(ColorChannelInterface $channel) => $channel->normalize(), $color->channels());
[$h, $s, $l] = array_map(
fn(ColorChannelInterface $channel): float => $channel->normalize(),
$color->channels()
);
$v = $l + $s * min($l, 1 - $l);
$s = ($v == 0) ? 0 : 2 * (1 - $l / $v);

View File

@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input');
}
$values = array_map(function ($value) {
$values = array_map(function (string $value): int {
return match (strpos($value, '%')) {
false => intval(trim($value)),
default => intval(trim(str_replace('%', '', $value))),

View File

@ -99,9 +99,8 @@ class Colorspace implements ColorspaceInterface
};
// add to each value
$values = array_map(fn($value) => $value + $color->value()->normalize() - $chroma, $values);
array_push($values, 1); // append alpha channel value
$values = array_map(fn(float|int $value): float => $value + $color->value()->normalize() - $chroma, $values);
$values[] = 1; // append alpha channel value
return $this->colorFromNormalized($values);
}
@ -118,8 +117,8 @@ class Colorspace implements ColorspaceInterface
}
// normalized values of hsl channels
list($h, $s, $l) = array_map(
fn(ColorChannelInterface $channel) => $channel->normalize(),
[$h, $s, $l] = array_map(
fn(ColorChannelInterface $channel): float => $channel->normalize(),
$color->channels()
);
@ -136,9 +135,8 @@ class Colorspace implements ColorspaceInterface
default => [$c, 0, $x],
};
$values = array_map(fn($value) => $value + $m, $values);
array_push($values, 1); // append alpha channel value
$values = array_map(fn(float|int $value): float => $value + $m, $values);
$values[] = 1; // append alpha channel value
return $this->colorFromNormalized($values);
}

View File

@ -30,14 +30,13 @@ class HexColorDecoder extends AbstractDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input');
}
$values = str_split($matches['hex']);
$values = match (strlen($matches['hex'])) {
3, 4 => str_split($matches['hex']),
6, 8 => str_split($matches['hex'], 2),
default => throw new DecoderException('Unable to decode input'),
};
$values = array_map(function ($value) {
$values = array_map(function (string $value): float|int {
return match (strlen($value)) {
1 => hexdec($value . $value),
2 => hexdec($value),

View File

@ -32,7 +32,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
}
// rgb values
$values = array_map(function ($value) {
$values = array_map(function (string $value): int {
return match (strpos($value, '%')) {
false => intval(trim($value)),
default => intval(round(floatval(trim(str_replace('%', '', $value))) / 100 * 255)),

View File

@ -21,7 +21,7 @@ class TransparentColorDecoder extends HexColorDecoder
throw new DecoderException('Unable to decode input');
}
if (strtolower($input) != 'transparent') {
if (strtolower($input) !== 'transparent') {
throw new DecoderException('Unable to decode input');
}

View File

@ -52,7 +52,7 @@ class Config
*/
private function prepareOptions(array $options): array
{
if (count($options) === 0) {
if ($options === []) {
return $options;
}

View File

@ -112,25 +112,18 @@ abstract class AbstractDecoder implements DecoderInterface
$pattern = "/^data:(?P<mediatype>\w+\/[-+.\w]+)?" .
"(?P<parameters>(;[-\w]+=[-\w]+)*)(?P<base64>;base64)?,(?P<data>.*)/";
$result = preg_match($pattern, $input, $matches);
$result = preg_match($pattern, (string) $input, $matches);
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)
public function __construct(private array $matches, private int|false $result)
{
$this->matches = $matches;
$this->result = $result;
//
}
public function isValid(): bool
@ -154,11 +147,7 @@ abstract class AbstractDecoder implements DecoderInterface
public function isBase64Encoded(): bool
{
if (isset($this->matches['base64']) && $this->matches['base64'] === ';base64') {
return true;
}
return false;
return isset($this->matches['base64']) && $this->matches['base64'] === ';base64';
}
public function data(): ?string

View File

@ -103,13 +103,16 @@ abstract class AbstractDriver implements DriverInterface
*/
public function specializeMultiple(array $objects): array
{
return array_map(function ($object) {
return $this->specialize(
match (true) {
is_string($object) => new $object(),
is_object($object) => $object,
}
);
}, $objects);
return array_map(
function (string|object $object): ModifierInterface|AnalyzerInterface|EncoderInterface|DecoderInterface {
return $this->specialize(
match (true) {
is_string($object) => new $object(),
is_object($object) => $object,
}
);
},
$objects
);
}
}

View File

@ -36,9 +36,9 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
foreach ($lines as $line) {
$lineBoxSize = $this->boxSize((string) $line, $font);
$lineWidth = $lineBoxSize->width() + $lineBoxSize->pivot()->x();
$xAdjustment = $font->alignment() == 'left' ? 0 : $blockWidth - $lineWidth;
$xAdjustment = $font->alignment() == 'right' ? intval(round($xAdjustment)) : $xAdjustment;
$xAdjustment = $font->alignment() == 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
$xAdjustment = $font->alignment() === 'left' ? 0 : $blockWidth - $lineWidth;
$xAdjustment = $font->alignment() === 'right' ? intval(round($xAdjustment)) : $xAdjustment;
$xAdjustment = $font->alignment() === 'center' ? intval(round($xAdjustment / 2)) : $xAdjustment;
$position = new Point($x + $xAdjustment, $y);
$position->rotate($font->angle(), $pivot);
$line->setPosition($position);
@ -132,14 +132,14 @@ abstract class AbstractFontProcessor implements FontProcessorInterface
// calculate width of newly formatted line
$lineWidth = $this->boxSize(match ($formattedLine->count()) {
0 => $word,
default => (string) $formattedLine . ' ' . $word,
default => $formattedLine . ' ' . $word,
}, $font)->width();
// decide if word fits on current line or a new line must be created
if ($line->count() === 1 || $lineWidth <= $font->wrapWidth()) {
$formattedLine->add($word);
} else {
if ($formattedLine->count()) {
if ($formattedLine->count() !== 0) {
$wrapped[] = $formattedLine;
}
$formattedLine = new Line($word);

View File

@ -22,6 +22,6 @@ class Base64ImageDecoder extends BinaryImageDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input');
}
return parent::decode(base64_decode($input));
return parent::decode(base64_decode((string) $input));
}
}

View File

@ -18,7 +18,7 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
*/
public function encode(ImageInterface $image): EncodedImage
{
return $this->createEncodedImage(function ($pointer) use ($image) {
return $this->createEncodedImage(function ($pointer) use ($image): void {
imageavif($image->core()->native(), $pointer, $this->quality);
}, 'image/avif');
}

View File

@ -18,7 +18,7 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
*/
public function encode(ImageInterface $image): EncodedImage
{
return $this->createEncodedImage(function ($pointer) use ($image) {
return $this->createEncodedImage(function ($pointer) use ($image): void {
imagebmp($image->core()->native(), $pointer, false);
}, 'image/bmp');
}

View File

@ -29,7 +29,7 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
$gd = Cloner::clone($image->core()->native());
return $this->createEncodedImage(function ($pointer) use ($gd) {
return $this->createEncodedImage(function ($pointer) use ($gd): void {
imageinterlace($gd, $this->interlaced);
imagegif($gd, $pointer);
}, 'image/gif');

View File

@ -28,7 +28,7 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
background: $blendingColor
);
return $this->createEncodedImage(function ($pointer) use ($output) {
return $this->createEncodedImage(function ($pointer) use ($output): void {
imageinterlace($output, $this->progressive);
imagejpeg($output, $pointer, $this->quality);
}, 'image/jpeg');

View File

@ -25,7 +25,7 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
{
$output = $this->prepareOutput($image);
return $this->createEncodedImage(function ($pointer) use ($output) {
return $this->createEncodedImage(function ($pointer) use ($output): void {
imageinterlace($output, $this->interlaced);
imagepng($output, $pointer, -1);
}, 'image/png');

View File

@ -20,7 +20,7 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
{
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality;
return $this->createEncodedImage(function ($pointer) use ($image, $quality) {
return $this->createEncodedImage(function ($pointer) use ($image, $quality): void {
imagewebp($image->core()->native(), $pointer, $quality);
}, 'image/webp');
}

View File

@ -19,7 +19,7 @@ class ColorspaceModifier extends GenericColorspaceModifier implements Specialize
*/
public function apply(ImageInterface $image): ImageInterface
{
if (!is_a($this->targetColorspace(), RgbColorspace::class)) {
if (!($this->targetColorspace() instanceof RgbColorspace)) {
throw new NotSupportedException(
'Only RGB colorspace is supported by GD driver.'
);

View File

@ -26,7 +26,7 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
throw new GeometryException('You must specify either 3 or 4 points to create a bezier curve');
}
list($polygon, $polygon_border_segments) = $this->calculateBezierPoints();
[$polygon, $polygon_border_segments] = $this->calculateBezierPoints();
if ($this->drawable->hasBackgroundColor() || $this->drawable->hasBorder()) {
imagealphablending($frame->native(), true);
@ -54,7 +54,8 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
if ($this->drawable->borderSize() === 1) {
imagesetthickness($frame->native(), $this->drawable->borderSize());
for ($i = 0; $i < count($polygon); $i += 2) {
$count = count($polygon);
for ($i = 0; $i < $count; $i += 2) {
if (array_key_exists($i + 2, $polygon) && array_key_exists($i + 3, $polygon)) {
imageline(
$frame->native(),
@ -160,11 +161,11 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
$polygon_border_segments = [];
// define ratio t; equivalent to 5 percent distance along edge
$t = (float) 0.05;
$t = 0.05;
$polygon[] = $this->drawable->first()->x();
$polygon[] = $this->drawable->first()->y();
for ($i = 0 + $t; $i < 1; $i += $t) {
for ($i = $t; $i < 1; $i += $t) {
if ($this->drawable->count() === 3) {
$ip = $this->calculateQuadraticBezierInterpolationPoint($i);
} elseif ($this->drawable->count() === 4) {

View File

@ -178,7 +178,7 @@ class Core implements CoreInterface, Iterator
*/
public function next(): void
{
$this->iteratorIndex = $this->iteratorIndex + 1;
$this->iteratorIndex += 1;
}
/**
@ -247,7 +247,7 @@ class Core implements CoreInterface, Iterator
public function frame(int $position): FrameInterface
{
foreach ($this->imagick as $core) {
if ($core->getIteratorIndex() == $position) {
if ($core->getIteratorIndex() === $position) {
return new Frame($core);
}
}

View File

@ -21,6 +21,6 @@ class Base64ImageDecoder extends BinaryImageDecoder
throw new DecoderException('Unable to decode input');
}
return parent::decode(base64_decode($input));
return parent::decode(base64_decode((string) $input));
}
}

View File

@ -35,7 +35,7 @@ class NativeObjectDecoder extends SpecializableDecoder implements SpecializedInt
// For some JPEG formats, the "coalesceImages()" call leads to an image
// completely filled with background color. The logic behind this is
// incomprehensible for me; could be an imagick bug.
if ($input->getImageFormat() != 'JPEG') {
if ($input->getImageFormat() !== 'JPEG') {
$input = $input->coalesceImages();
}

View File

@ -63,7 +63,7 @@ class FontProcessor extends AbstractFontProcessor
$draw->setFontSize($this->nativeFontSize($font));
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
if ($color) {
if ($color instanceof ImagickPixel) {
$draw->setFillColor($color);
}

View File

@ -13,7 +13,7 @@ class BlurModifier extends GenericBlurModifier implements SpecializedInterface
public function apply(ImageInterface $image): ImageInterface
{
foreach ($image as $frame) {
$frame->native()->blurImage(1 * $this->amount, 0.5 * $this->amount);
$frame->native()->blurImage($this->amount, 0.5 * $this->amount);
}
return $image;

View File

@ -122,7 +122,7 @@ class TextModifier extends GenericTextModifier implements SpecializedInterface
?ImagickDraw $draw = null,
PointInterface $offset = new Point(),
): void {
if ($draw !== null) {
if ($draw instanceof ImagickDraw) {
$frame->native()->annotateImage(
$draw,
$textline->position()->x() + $offset->x(),

View File

@ -8,8 +8,9 @@ use Intervention\Image\Exceptions\NotWritableException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FileInterface;
use Intervention\Image\Traits\CanBuildFilePointer;
use Stringable;
class File implements FileInterface
class File implements FileInterface, Stringable
{
use CanBuildFilePointer;
@ -64,7 +65,7 @@ class File implements FileInterface
if (is_file($filepath) && !is_writable($filepath)) {
throw new NotWritableException(
"Can't write image. Path ({$filepath}) is not writable."
sprintf("Can't write image. Path (%s) is not writable.", $filepath)
);
}
@ -72,7 +73,7 @@ class File implements FileInterface
$saved = @file_put_contents($filepath, $this->pointer);
if ($saved === false) {
throw new NotWritableException(
"Can't write image data to path ({$filepath})."
sprintf("Can't write image data to path (%s).", $filepath)
);
}
}

View File

@ -88,7 +88,7 @@ enum Format
{
return array_filter(
MediaType::cases(),
fn(MediaType $mediaType) => $mediaType->format() === $this
fn(MediaType $mediaType): bool => $mediaType->format() === $this
);
}
@ -113,7 +113,7 @@ enum Format
{
return array_filter(
FileExtension::cases(),
fn(FileExtension $fileExtension) => $fileExtension->format() === $this
fn(FileExtension $fileExtension): bool => $fileExtension->format() === $this
);
}
@ -155,7 +155,7 @@ enum Format
$reflectionClass = new ReflectionClass($classname);
if ($constructor = $reflectionClass->getConstructor()) {
$parameters = array_map(
fn($parameter) => $parameter->getName(),
fn($parameter): string => $parameter->getName(),
$constructor->getParameters(),
);
}
@ -163,7 +163,7 @@ enum Format
// filter out unavailable options of target encoder
$options = array_filter(
$options,
fn($key) => in_array($key, $parameters),
fn($key): bool => in_array($key, $parameters),
ARRAY_FILTER_USE_KEY,
);

View File

@ -214,12 +214,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
*/
public function mostLeftPoint(): PointInterface
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
$points = $this->points;
usort($points, function ($a, $b) {
usort($points, function (PointInterface $a, PointInterface $b): int {
if ($a->x() === $b->x()) {
return 0;
}
@ -236,12 +233,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
*/
public function mostRightPoint(): PointInterface
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
$points = $this->points;
usort($points, function ($a, $b) {
usort($points, function (PointInterface $a, PointInterface $b): int {
if ($a->x() === $b->x()) {
return 0;
}
@ -258,12 +252,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
*/
public function mostTopPoint(): PointInterface
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
$points = $this->points;
usort($points, function ($a, $b) {
usort($points, function (PointInterface $a, PointInterface $b): int {
if ($a->y() === $b->y()) {
return 0;
}
@ -280,12 +271,9 @@ class Polygon implements IteratorAggregate, Countable, ArrayAccess, DrawableInte
*/
public function mostBottomPoint(): PointInterface
{
$points = [];
foreach ($this->points as $point) {
$points[] = $point;
}
$points = $this->points;
usort($points, function ($a, $b) {
usort($points, function (PointInterface $a, PointInterface $b): int {
if ($a->y() === $b->y()) {
return 0;
}

View File

@ -111,13 +111,13 @@ class Rectangle extends Polygon implements SizeInterface
case 'center-top':
case 'middle-top':
$x = intval(round($this->width() / 2)) + $offset_x;
$y = 0 + $offset_y;
$y = $offset_y;
break;
case 'top-right':
case 'right-top':
$x = $this->width() - $offset_x;
$y = 0 + $offset_y;
$y = $offset_y;
break;
case 'left':
@ -125,7 +125,7 @@ class Rectangle extends Polygon implements SizeInterface
case 'left-middle':
case 'center-left':
case 'middle-left':
$x = 0 + $offset_x;
$x = $offset_x;
$y = intval(round($this->height() / 2)) + $offset_y;
break;
@ -140,7 +140,7 @@ class Rectangle extends Polygon implements SizeInterface
case 'bottom-left':
case 'left-bottom':
$x = 0 + $offset_x;
$x = $offset_x;
$y = $this->height() - $offset_y;
break;
@ -170,8 +170,8 @@ class Rectangle extends Polygon implements SizeInterface
default:
case 'top-left':
case 'left-top':
$x = 0 + $offset_x;
$y = 0 + $offset_y;
$x = $offset_x;
$y = $offset_y;
break;
}

View File

@ -52,7 +52,7 @@ class RectangleResizer
*/
protected function hasTargetWidth(): bool
{
return is_integer($this->width);
return is_int($this->width);
}
/**
@ -72,7 +72,7 @@ class RectangleResizer
*/
protected function hasTargetHeight(): bool
{
return is_integer($this->height);
return is_int($this->height);
}
/**

View File

@ -107,7 +107,7 @@ final class Image implements ImageInterface
*
* @var Origin
*/
protected Origin $origin;
private Origin $origin;
/**
* Create new instance
@ -119,9 +119,9 @@ final class Image implements ImageInterface
* @return void
*/
public function __construct(
protected DriverInterface $driver,
protected CoreInterface $core,
protected CollectionInterface $exif = new Collection()
private DriverInterface $driver,
private CoreInterface $core,
private CollectionInterface $exif = new Collection()
) {
$this->origin = new Origin();
}

View File

@ -14,7 +14,7 @@ use Intervention\Image\Interfaces\ImageManagerInterface;
final class ImageManager implements ImageManagerInterface
{
protected DriverInterface $driver;
private DriverInterface $driver;
/**
* @link https://image.intervention.io/v3/basics/image-manager#create-a-new-image-manager-instance

View File

@ -17,6 +17,6 @@ class FillModifier extends SpecializableModifier
public function hasPosition(): bool
{
return !empty($this->position);
return $this->position instanceof PointInterface;
}
}

View File

@ -50,8 +50,7 @@ class RemoveAnimationModifier extends SpecializableModifier
$total = count($image);
$position = intval(round($total / 100 * intval($matches['percent'])));
$position = $position == $total ? $position - 1 : $position;
return $position;
return $position == $total ? $position - 1 : $position;
}
}

View File

@ -5,8 +5,9 @@ declare(strict_types=1);
namespace Intervention\Image;
use Intervention\Image\Interfaces\ResolutionInterface;
use Stringable;
class Resolution implements ResolutionInterface
class Resolution implements ResolutionInterface, Stringable
{
public const PER_INCH = 1;
public const PER_CM = 2;

View File

@ -9,12 +9,13 @@ use Countable;
use Intervention\Image\Geometry\Point;
use Intervention\Image\Interfaces\PointInterface;
use IteratorAggregate;
use Stringable;
use Traversable;
/**
* @implements IteratorAggregate<string>
*/
class Line implements IteratorAggregate, Countable
class Line implements IteratorAggregate, Countable, Stringable
{
/**
* Segments (usually individual words including punctuation marks) of the line

View File

@ -67,7 +67,7 @@ class TextBlock extends Collection
public function longestLine(): Line
{
$lines = $this->lines();
usort($lines, function (Line $a, Line $b) {
usort($lines, function (Line $a, Line $b): int {
if ($a->length() === $b->length()) {
return 0;
}