1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-04 04:47:25 +02: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
44 changed files with 108 additions and 123 deletions

View File

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

View File

@@ -153,7 +153,7 @@ class Collection implements CollectionInterface, IteratorAggregate, Countable
return $this->items[$query]; 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; 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\ColorInterface;
use Intervention\Image\Interfaces\ColorspaceInterface; use Intervention\Image\Interfaces\ColorspaceInterface;
use ReflectionClass; use ReflectionClass;
use Stringable;
abstract class AbstractColor implements ColorInterface abstract class AbstractColor implements ColorInterface, Stringable
{ {
/** /**
* Color channels * Color channels
@@ -38,7 +39,7 @@ abstract class AbstractColor implements ColorInterface
{ {
$channels = array_filter( $channels = array_filter(
$this->channels(), $this->channels(),
fn(ColorChannelInterface $channel) => $channel::class == $classname, fn(ColorChannelInterface $channel): bool => $channel::class === $classname,
); );
if (count($channels) == 0) { if (count($channels) == 0) {
@@ -56,7 +57,7 @@ abstract class AbstractColor implements ColorInterface
public function normalize(): array public function normalize(): array
{ {
return array_map( return array_map(
fn(ColorChannelInterface $channel) => $channel->normalize(), fn(ColorChannelInterface $channel): float => $channel->normalize(),
$this->channels(), $this->channels(),
); );
} }
@@ -69,7 +70,7 @@ abstract class AbstractColor implements ColorInterface
public function toArray(): array public function toArray(): array
{ {
return array_map( return array_map(
fn(ColorChannelInterface $channel) => $channel->value(), fn(ColorChannelInterface $channel): int => $channel->value(),
$this->channels() $this->channels()
); );
} }

View File

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

View File

@@ -30,7 +30,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input'); 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))))); return intval(round(floatval(trim(str_replace('%', '', $value)))));
}, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]); }, [$matches['c'], $matches['m'], $matches['y'], $matches['k']]);

View File

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

View File

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

View File

@@ -67,7 +67,7 @@ class Colorspace implements ColorspaceInterface
} }
// normalized values of rgb channels // 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 // take only RGB
$values = array_slice($values, 0, 3); $values = array_slice($values, 0, 3);
@@ -89,7 +89,7 @@ class Colorspace implements ColorspaceInterface
$s = 100 * ($chroma / $max); $s = 100 * ($chroma / $max);
// calculate hue // calculate hue
list($r, $g, $b) = $values; [$r, $g, $b] = $values;
$h = match (true) { $h = match (true) {
($r == $min) => 3 - (($g - $b) / $chroma), ($r == $min) => 3 - (($g - $b) / $chroma),
($b == $min) => 1 - (($r - $g) / $chroma), ($b == $min) => 1 - (($r - $g) / $chroma),
@@ -115,7 +115,10 @@ class Colorspace implements ColorspaceInterface
} }
// normalized values of hsl channels // 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); $v = $l + $s * min($l, 1 - $l);
$s = ($v == 0) ? 0 : 2 * (1 - $l / $v); $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'); throw new DecoderException('Unable to decode input');
} }
$values = array_map(function ($value) { $values = array_map(function (string $value): int {
return match (strpos($value, '%')) { return match (strpos($value, '%')) {
false => intval(trim($value)), false => intval(trim($value)),
default => intval(trim(str_replace('%', '', $value))), default => intval(trim(str_replace('%', '', $value))),

View File

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

View File

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

View File

@@ -32,7 +32,7 @@ class StringColorDecoder extends AbstractDecoder implements DecoderInterface
} }
// rgb values // rgb values
$values = array_map(function ($value) { $values = array_map(function (string $value): int {
return match (strpos($value, '%')) { return match (strpos($value, '%')) {
false => intval(trim($value)), false => intval(trim($value)),
default => intval(round(floatval(trim(str_replace('%', '', $value))) / 100 * 255)), 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'); throw new DecoderException('Unable to decode input');
} }
if (strtolower($input) != 'transparent') { if (strtolower($input) !== 'transparent') {
throw new DecoderException('Unable to decode input'); throw new DecoderException('Unable to decode input');
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,6 +22,6 @@ class Base64ImageDecoder extends BinaryImageDecoder implements DecoderInterface
throw new DecoderException('Unable to decode input'); 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 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); imageavif($image->core()->native(), $pointer, $this->quality);
}, 'image/avif'); }, 'image/avif');
} }

View File

@@ -18,7 +18,7 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
*/ */
public function encode(ImageInterface $image): EncodedImage 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); imagebmp($image->core()->native(), $pointer, false);
}, 'image/bmp'); }, 'image/bmp');
} }

View File

@@ -29,7 +29,7 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
$gd = Cloner::clone($image->core()->native()); $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); imageinterlace($gd, $this->interlaced);
imagegif($gd, $pointer); imagegif($gd, $pointer);
}, 'image/gif'); }, 'image/gif');

View File

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

View File

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

View File

@@ -20,7 +20,7 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
{ {
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality; $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); imagewebp($image->core()->native(), $pointer, $quality);
}, 'image/webp'); }, 'image/webp');
} }

View File

@@ -19,7 +19,7 @@ class ColorspaceModifier extends GenericColorspaceModifier implements Specialize
*/ */
public function apply(ImageInterface $image): ImageInterface public function apply(ImageInterface $image): ImageInterface
{ {
if (!is_a($this->targetColorspace(), RgbColorspace::class)) { if (!($this->targetColorspace() instanceof RgbColorspace)) {
throw new NotSupportedException( throw new NotSupportedException(
'Only RGB colorspace is supported by GD driver.' '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'); 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()) { if ($this->drawable->hasBackgroundColor() || $this->drawable->hasBorder()) {
imagealphablending($frame->native(), true); imagealphablending($frame->native(), true);
@@ -54,7 +54,8 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
if ($this->drawable->borderSize() === 1) { if ($this->drawable->borderSize() === 1) {
imagesetthickness($frame->native(), $this->drawable->borderSize()); 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)) { if (array_key_exists($i + 2, $polygon) && array_key_exists($i + 3, $polygon)) {
imageline( imageline(
$frame->native(), $frame->native(),
@@ -160,11 +161,11 @@ class DrawBezierModifier extends ModifiersDrawBezierModifier implements Speciali
$polygon_border_segments = []; $polygon_border_segments = [];
// define ratio t; equivalent to 5 percent distance along edge // 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()->x();
$polygon[] = $this->drawable->first()->y(); $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) { if ($this->drawable->count() === 3) {
$ip = $this->calculateQuadraticBezierInterpolationPoint($i); $ip = $this->calculateQuadraticBezierInterpolationPoint($i);
} elseif ($this->drawable->count() === 4) { } elseif ($this->drawable->count() === 4) {

View File

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

View File

@@ -21,6 +21,6 @@ class Base64ImageDecoder extends BinaryImageDecoder
throw new DecoderException('Unable to decode input'); 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 // For some JPEG formats, the "coalesceImages()" call leads to an image
// completely filled with background color. The logic behind this is // completely filled with background color. The logic behind this is
// incomprehensible for me; could be an imagick bug. // incomprehensible for me; could be an imagick bug.
if ($input->getImageFormat() != 'JPEG') { if ($input->getImageFormat() !== 'JPEG') {
$input = $input->coalesceImages(); $input = $input->coalesceImages();
} }

View File

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

View File

@@ -13,7 +13,7 @@ class BlurModifier extends GenericBlurModifier implements SpecializedInterface
public function apply(ImageInterface $image): ImageInterface public function apply(ImageInterface $image): ImageInterface
{ {
foreach ($image as $frame) { 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; return $image;

View File

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

View File

@@ -8,8 +8,9 @@ use Intervention\Image\Exceptions\NotWritableException;
use Intervention\Image\Exceptions\RuntimeException; use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FileInterface; use Intervention\Image\Interfaces\FileInterface;
use Intervention\Image\Traits\CanBuildFilePointer; use Intervention\Image\Traits\CanBuildFilePointer;
use Stringable;
class File implements FileInterface class File implements FileInterface, Stringable
{ {
use CanBuildFilePointer; use CanBuildFilePointer;
@@ -64,7 +65,7 @@ class File implements FileInterface
if (is_file($filepath) && !is_writable($filepath)) { if (is_file($filepath) && !is_writable($filepath)) {
throw new NotWritableException( 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); $saved = @file_put_contents($filepath, $this->pointer);
if ($saved === false) { if ($saved === false) {
throw new NotWritableException( 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( return array_filter(
MediaType::cases(), MediaType::cases(),
fn(MediaType $mediaType) => $mediaType->format() === $this fn(MediaType $mediaType): bool => $mediaType->format() === $this
); );
} }
@@ -113,7 +113,7 @@ enum Format
{ {
return array_filter( return array_filter(
FileExtension::cases(), 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); $reflectionClass = new ReflectionClass($classname);
if ($constructor = $reflectionClass->getConstructor()) { if ($constructor = $reflectionClass->getConstructor()) {
$parameters = array_map( $parameters = array_map(
fn($parameter) => $parameter->getName(), fn($parameter): string => $parameter->getName(),
$constructor->getParameters(), $constructor->getParameters(),
); );
} }
@@ -163,7 +163,7 @@ enum Format
// filter out unavailable options of target encoder // filter out unavailable options of target encoder
$options = array_filter( $options = array_filter(
$options, $options,
fn($key) => in_array($key, $parameters), fn($key): bool => in_array($key, $parameters),
ARRAY_FILTER_USE_KEY, ARRAY_FILTER_USE_KEY,
); );

View File

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

View File

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

View File

@@ -52,7 +52,7 @@ class RectangleResizer
*/ */
protected function hasTargetWidth(): bool protected function hasTargetWidth(): bool
{ {
return is_integer($this->width); return is_int($this->width);
} }
/** /**
@@ -72,7 +72,7 @@ class RectangleResizer
*/ */
protected function hasTargetHeight(): bool 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 * @var Origin
*/ */
protected Origin $origin; private Origin $origin;
/** /**
* Create new instance * Create new instance
@@ -119,9 +119,9 @@ final class Image implements ImageInterface
* @return void * @return void
*/ */
public function __construct( public function __construct(
protected DriverInterface $driver, private DriverInterface $driver,
protected CoreInterface $core, private CoreInterface $core,
protected CollectionInterface $exif = new Collection() private CollectionInterface $exif = new Collection()
) { ) {
$this->origin = new Origin(); $this->origin = new Origin();
} }

View File

@@ -14,7 +14,7 @@ use Intervention\Image\Interfaces\ImageManagerInterface;
final class ImageManager implements 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 * @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 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); $total = count($image);
$position = intval(round($total / 100 * intval($matches['percent']))); $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; namespace Intervention\Image;
use Intervention\Image\Interfaces\ResolutionInterface; use Intervention\Image\Interfaces\ResolutionInterface;
use Stringable;
class Resolution implements ResolutionInterface class Resolution implements ResolutionInterface, Stringable
{ {
public const PER_INCH = 1; public const PER_INCH = 1;
public const PER_CM = 2; public const PER_CM = 2;

View File

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

View File

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