Skip to content

Commit

Permalink
refactoring, stricter phpstan, moved from arrays to objects, better t…
Browse files Browse the repository at this point in the history
…ests, more exceptions
  • Loading branch information
Gappa committed Nov 29, 2021
1 parent 94f05f8 commit c1ab6c9
Show file tree
Hide file tree
Showing 14 changed files with 875 additions and 456 deletions.
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
"require-dev": {
"nette/tester": "^2.0",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.0",
"phpstan/phpstan-nette": "^0.12.0",
"roave/security-advisories": "dev-master"
"phpstan/phpstan": "^1.0.0",
"phpstan/phpstan-nette": "^1.0.0",
"roave/security-advisories": "dev-master",
"tracy/tracy": "^2.8"
},
"autoload": {
"psr-4": {
Expand Down
2 changes: 0 additions & 2 deletions phpstan/phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ parameters:
- ../src/

level: 7

checkMissingIterableValueType: false
10 changes: 8 additions & 2 deletions src/DI/ResizerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ final class ResizerConfig
public string $wwwDir;
public string $tempDir;
public string $cache = '/resizer/';
public bool $upgradeJpg2Webp = true;
public bool $strip = true;

/** @var int<0, 100> */
public int $qualityWebp;

/** @var int<0, 100> */
public int $qualityJpeg;

/** @var int<0, 9> */
public int $compressionPng;
public bool $upgradeJpg2Webp = true;
public bool $strip = true;
}
39 changes: 39 additions & 0 deletions src/Dimensions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Nelson\Resizer;

class Dimensions
{

private int $width;
private int $height;


public function __construct(
int $width,
int $height
)
{
$this->width = $width;
$this->height = $height;
}


public function getWidth(): int
{
return $this->width;
}


public function getHeight(): int
{
return $this->height;
}


public function getRatio(): float
{
return $this->width / $this->height;
}

}
11 changes: 11 additions & 0 deletions src/Exceptions/CouldNotParseResizerParamsException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace Nelson\Resizer\Exceptions;

use Exception;

final class CouldNotParseResizerParamsException extends Exception
{

}
11 changes: 11 additions & 0 deletions src/Exceptions/IncompatibleResizerParamsException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

namespace Nelson\Resizer\Exceptions;

use Exception;

final class IncompatibleResizerParamsException extends Exception
{

}
169 changes: 71 additions & 98 deletions src/Geometry.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,170 +4,143 @@
namespace Nelson\Resizer;

use Imagine\Image\Point;
use Nelson\Resizer\Exceptions\IncompatibleResizerParamsException;
use Nette\InvalidArgumentException;
use Nette\SmartObject;

class Geometry
final class Geometry
{
use SmartObject;

/**
* @param array|string|null $geometry
* @return array|null
*/
public static function parseGeometry($geometry): ?array
{
if (is_array($geometry)) {
return $geometry;
} elseif ($geometry === null) {
return null;
} elseif (is_string($geometry) && strlen($geometry) === 0) {
return null;
}

$pattern = '#(?:(ifresize)-)?([lcr]?)(\d*)x([tcb]?)(\d*)([!]?)([+-]?[0-9]*)([+-]?[0-9]*)#';

if (preg_match($pattern, $geometry, $matches)) {
return [
'ifresize' => (bool) $matches[1],
'horizontal' => $matches[2],
'vertical' => $matches[4],
'width' => (int) $matches[3],
'height' => (int) $matches[5],
'suffix' => $matches[6],
'horizontalMargin' => $matches[7],
'verticalMargin' => $matches[8],
];
}
private ResizerParams $resizerParams;

return null;

public function __construct(string $rawParams)
{
$this->resizerParams = (new ResizerParamsParser($rawParams))->getParams();
}


public static function calculateNewSize(array $srcSize, ?array $geometry): array
public function getResizerParams(): ResizerParams
{
// Geometry is empty, use fallback
if (empty($geometry)) {
return $srcSize;
}
return $this->resizerParams;
}

$desiredSize = $dstSize = [
'width' => $geometry['width'],
'height' => $geometry['height'],
];

// No params are set, use the image's dimensions
if (!array_filter($geometry)) {
return $srcSize;
public function calculateNewSize(Dimensions $input): Dimensions
{
// Shortcut
$rp = $this->resizerParams;

// This should not happen, has to be one or the other
if ($rp->isCrop() && $rp->isIfResize()) {
throw new IncompatibleResizerParamsException('Crop and IfResize can not be used together.');
}

// If params force a dimension, use them
if (!empty($geometry['suffix']) || (strpos($geometry['suffix'], '!') !== false)) {
return $desiredSize;
// No dimensions set, use fallback
if ($rp->hasNoDimensions()) {
return $input;
}

// This should not happen, has to be one or the other
if (static::isCrop($geometry) && static::isIfResize($geometry)) {
throw new InvalidArgumentException('Crop and IfResize can not be used together.');
// If params force a dimension, use them without any calculation
if ($rp->getForceDimensions() && $rp->hasBothDimensions()) {
return new Dimensions($rp->getWidth(), $rp->getHeight());
}

// -------------------------------

$srcRatio = $srcSize['width'] / $srcSize['height']; // real AR
if (!empty($desiredSize['width']) && !empty($desiredSize['height'])) {
$desiredRatio = $desiredSize['width'] / $desiredSize['height']; // possibly wanted AR
$inputRatio = $input->getRatio();

if ($rp->hasBothDimensions()) {
// possibly wanted AR
$desiredRatio = $rp->getWidth() / $rp->getHeight();
} else {
$desiredRatio = $srcRatio;
$desiredRatio = $inputRatio;
}

if ($desiredRatio <= $srcRatio && !empty($desiredSize['width'])) { // output width will respect the params
$outputRatio = $desiredSize['width'] / $srcSize['width'];
} elseif (!empty($desiredSize['height'])) { // output height will respect the params
$outputRatio = $desiredSize['height'] / $srcSize['height'];
// output width will respect the params
if ($desiredRatio <= $inputRatio && $rp->hasWidth()) {
$outputRatio = $rp->getWidth() / $input->getWidth();
}
// output height will respect the params
elseif ($rp->hasHeight()) {
$outputRatio = $rp->getHeight() / $input->getHeight();
} else {
$outputRatio = $srcRatio;
$outputRatio = $inputRatio;
}

$dstSize['width'] = round($srcSize['width'] * $outputRatio);
$dstSize['height'] = round($srcSize['height'] * $outputRatio);
$output = new Dimensions(
(int) round($input->getWidth() * $outputRatio),
(int) round($input->getHeight() * $outputRatio),
);

// Need to scale up to make room for the crop again
if (static::isCrop($geometry)) {
if ($dstSize['width'] == $geometry['width']) {
$dstSize['width'] = round($dstSize['width'] * $geometry['height'] / $dstSize['height']);
$dstSize['height'] = $geometry['height'];
if ($rp->isCrop()) {
if ($output->getWidth() === $rp->getWidth()) {
$width = $output->getWidth() * $rp->getHeight() / $output->getHeight();
$height = $rp->getHeight();
} else {
$dstSize['height'] = round($dstSize['height'] * $geometry['width'] / $dstSize['width']);
$dstSize['width'] = $geometry['width'];
$width = $rp->getWidth();
$height = $output->getHeight() * $rp->getWidth() / $output->getWidth();
}

$output = new Dimensions(
(int) round($width),
(int) round($height),
);
}

// If the image is smaller than the desired size, hijack the process
if (static::isIfResize($geometry)
if ($rp->isIfresize()
&& (
$geometry['width'] > $srcSize['width'] && $geometry['height'] > $srcSize['height']
|| $geometry['width'] > $srcSize['width'] && $geometry['height'] == 0
|| $geometry['height'] > $srcSize['height'] && $geometry['width'] == 0
$rp->getWidth() > $input->getWidth() && $rp->getHeight() > $input->getHeight()
||
$rp->getWidth() > $input->getWidth() && !$rp->hasHeight()
||
$rp->getHeight() > $input->getHeight() && !$rp->hasWidth()
)
) {
$dstSize['width'] = $srcSize['width'];
$dstSize['height'] = $srcSize['height'];
$output = new Dimensions($input->getWidth(), $input->getHeight());
}

return $dstSize;
return $output;
}


public static function isCrop(?array $geometry): bool
public function getCropPoint(Dimensions $source): Point
{
return !empty($geometry['horizontal']) && !empty($geometry['vertical']);
}


public static function isIfResize(array $geometry): bool
{
return !empty($geometry['ifresize']);
}


public static function getCropPoint(?array $geometry, array $imageOutputSize): Point
{
switch ($geometry['horizontal']) {
case 'l':
$x = 0;
break;

switch ($this->resizerParams->getHorizontal()) {
case 'c':
$x = ($imageOutputSize['width'] - $geometry['width']) / 2;
$x = ($source->getWidth() - $this->resizerParams->getWidth()) / 2;
break;

case 'r':
$x = $imageOutputSize['width'] - $geometry['width'];
$x = $source->getWidth() - $this->resizerParams->getWidth();
break;

case 'l':
default:
$x = 0;
break;
}

switch ($geometry['vertical']) {
case 't':
$y = 0;
break;

switch ($this->resizerParams->getVertical()) {
case 'c':
$y = ($imageOutputSize['height'] - $geometry['height']) / 2;
$y = ($source->getHeight() - $this->resizerParams->getHeight()) / 2;
break;

case 'b':
$y = $imageOutputSize['height'] - $geometry['height'];
$y = $source->getHeight() - $this->resizerParams->getHeight();
break;

case 't':
default:
$y = 0;
break;
}

return new Point((int) $x, (int) $y);
}

}
Loading

0 comments on commit c1ab6c9

Please sign in to comment.