diff --git a/index.php b/index.php index e3c8759..fde839a 100644 --- a/index.php +++ b/index.php @@ -41,6 +41,7 @@ 'LukasBestle\Roomle\Parameter' => __DIR__ . '/src/classes/Parameter.php', 'LukasBestle\Roomle\Parameters' => __DIR__ . '/src/classes/Parameters.php', 'LukasBestle\Roomle\Part' => __DIR__ . '/src/classes/Part.php', + 'LukasBestle\Roomle\Size' => __DIR__ . '/src/classes/Size.php', ]); // register the plugin diff --git a/src/classes/Configuration.php b/src/classes/Configuration.php index 58eaee7..211583f 100644 --- a/src/classes/Configuration.php +++ b/src/classes/Configuration.php @@ -9,7 +9,6 @@ use Kirby\Toolkit\Collection; use Kirby\Toolkit\Obj; use Kirby\Toolkit\Str; -use NumberFormatter; /** * Configuration @@ -134,41 +133,6 @@ public function configuratorUrl(): string|null return null; } - /** - * Returns the depth of the configured product - * as a human-readable string in cm - */ - public function depthLabel(): string - { - return static::formatLength($this->depth); - } - - /** - * Formats a length in millimeters as a - * human-readable string in cm - * @internal - */ - public static function formatLength(int $millimeters): string - { - $centimeters = $millimeters / 10; - - if (class_exists(NumberFormatter::class) === true) { - $formatter = new NumberFormatter(locale_get_default(), NumberFormatter::DECIMAL); - return $formatter->format($centimeters) . ' cm'; - } - - return $centimeters . ' cm'; // @codeCoverageIgnore - } - - /** - * Returns the height of the configured product - * as a human-readable string in cm - */ - public function heightLabel(): string - { - return static::formatLength($this->height); - } - /** * Creates an instance if data is available * (either from the argument or the request) @@ -223,19 +187,22 @@ public function perspectiveImage(): Image } /** - * Returns the image of a top view of the configured product + * Returns a size object for the configuration */ - public function topImage(): Image + public function size(): Size { - return new Image(['url' => $this->topImage]); + return new Size([ + 'depth' => $this->depth, + 'height' => $this->height, + 'width' => $this->width, + ]); } /** - * Returns the width of the configured product - * as a human-readable string in cm + * Returns the image of a top view of the configured product */ - public function widthLabel(): string + public function topImage(): Image { - return static::formatLength($this->width); + return new Image(['url' => $this->topImage]); } } diff --git a/src/classes/Parameter.php b/src/classes/Parameter.php index ec333ce..a37d03f 100644 --- a/src/classes/Parameter.php +++ b/src/classes/Parameter.php @@ -99,7 +99,7 @@ public function valueLabel(): string /** @var float $value */ $value = $this->value(); - return Configuration::formatLength((int)$value); + return Size::formatLength((int)$value); } return $this->valueLabel ?? $this->value; diff --git a/src/classes/Part.php b/src/classes/Part.php index 1f79dea..3cb27c2 100644 --- a/src/classes/Part.php +++ b/src/classes/Part.php @@ -109,4 +109,25 @@ public function parameters(): Parameters return new Parameters($parameters); } + + /** + * Returns a size object for the part + */ + public function size(): Size + { + $parameters = $this->parameters(); + + $data = []; + foreach (['depth', 'height', 'width'] as $parameter) { + $value = $parameters->get($parameter)?->value(); + + if (is_float($value) !== true) { + throw new InvalidArgumentException('Invalid ' . $parameter . ' value'); + } + + $data[$parameter] = (int)$value; + } + + return new Size($data); + } } diff --git a/src/classes/Size.php b/src/classes/Size.php new file mode 100644 index 0000000..844da89 --- /dev/null +++ b/src/classes/Size.php @@ -0,0 +1,93 @@ + + * @link https://github.com/lukasbestle/kirby-roomle + * @copyright Lukas Bestle + * @license https://opensource.org/licenses/MIT + * + * @psalm-suppress PropertyNotSetInConstructor + */ +class Size extends Obj +{ + /** + * Depth in mm + */ + public int $depth; + + /** + * Height in mm + */ + public int $height; + + /** + * Width in mm + */ + public int $width; + + /** + * Returns a human-readable string of the size + */ + public function __toString(): string + { + return I18n::template('roomle.size', '', [ + 'depth' => $this->depthLabel(), + 'height' => $this->heightLabel(), + 'width' => $this->widthLabel(), + ]); + } + + /** + * Returns the depth of the configured product + * as a human-readable string in cm + */ + public function depthLabel(): string + { + return static::formatLength($this->depth); + } + + /** + * Formats a length in millimeters as a + * human-readable string in cm + * @internal + */ + public static function formatLength(int $millimeters): string + { + $centimeters = $millimeters / 10; + + if (class_exists(NumberFormatter::class) === true) { + $formatter = new NumberFormatter(locale_get_default(), NumberFormatter::DECIMAL); + return $formatter->format($centimeters) . ' cm'; + } + + return $centimeters . ' cm'; // @codeCoverageIgnore + } + + /** + * Returns the height of the configured product + * as a human-readable string in cm + */ + public function heightLabel(): string + { + return static::formatLength($this->height); + } + + /** + * Returns the width of the configured product + * as a human-readable string in cm + */ + public function widthLabel(): string + { + return static::formatLength($this->width); + } +} diff --git a/src/config/i18n/de.php b/src/config/i18n/de.php index 2d578d1..ee93f42 100644 --- a/src/config/i18n/de.php +++ b/src/config/i18n/de.php @@ -3,4 +3,5 @@ return [ 'roomle.empty' => 'Noch kein gültiges Hauptprodukt', 'roomle.noRendering' => 'Kein Rendering verfügbar', + 'roomle.size' => 'B { width } / H { height } / T { depth }', ]; diff --git a/src/config/i18n/en.php b/src/config/i18n/en.php index 342d878..3785ba4 100644 --- a/src/config/i18n/en.php +++ b/src/config/i18n/en.php @@ -3,4 +3,5 @@ return [ 'roomle.empty' => 'No valid main product yet', 'roomle.noRendering' => 'No rendering available', + 'roomle.size' => 'W { width } / H { height } / D { depth }', ]; diff --git a/src/config/snippets/roomle/configuration.php b/src/config/snippets/roomle/configuration.php index b11fc9e..314be3d 100644 --- a/src/config/snippets/roomle/configuration.php +++ b/src/config/snippets/roomle/configuration.php @@ -1,6 +1,6 @@ label() ?> (id() ?>) -W widthLabel() ?> / H heightLabel() ?> / D depthLabel() . "\n" ?> +size() . "\n" ?> configuratorUrl() . "\n" ?> parts() as $part): ?> diff --git a/tests/Roomle/ConfigurationTest.php b/tests/Roomle/ConfigurationTest.php index 57ea686..26ee04b 100644 --- a/tests/Roomle/ConfigurationTest.php +++ b/tests/Roomle/ConfigurationTest.php @@ -124,36 +124,6 @@ public function testConstruct_StringInvalid() new Configuration('Definitely not JSON'); } - /** - * @covers ::formatLength - */ - public function testFormatLength() - { - $this->assertSame('0.1 cm', Configuration::formatLength(1)); - $this->assertSame('1 cm', Configuration::formatLength(10)); - $this->assertSame('1.3 cm', Configuration::formatLength(13)); - $this->assertSame('123.4 cm', Configuration::formatLength(1234)); - $this->assertSame('1,234.5 cm', Configuration::formatLength(12345)); - } - - /** - * @covers ::depthLabel - * @covers ::heightLabel - * @covers ::widthLabel - */ - public function testLengthLabels() - { - $configuration = new Configuration([ - 'depth' => 12345, - 'height' => 34567, - 'width' => 56789 - ]); - - $this->assertSame('1,234.5 cm', $configuration->depthLabel()); - $this->assertSame('3,456.7 cm', $configuration->heightLabel()); - $this->assertSame('5,678.9 cm', $configuration->widthLabel()); - } - /** * @covers ::parts */ @@ -231,6 +201,21 @@ public function testPerspectiveImage() $this->assertSame('', $image->html()); } + /** + * @covers ::size + */ + public function testSize() + { + $configuration = new Configuration([ + 'depth' => 12345, + 'height' => 34567, + 'width' => 56789 + ]); + + $this->assertSame('W 5,678.9 cm / H 3,456.7 cm / D 1,234.5 cm', (string)$configuration->size()); + $this->assertSame('5,678.9 cm', $configuration->size()->widthLabel()); + } + /** * @covers ::topImage */ diff --git a/tests/Roomle/PartTest.php b/tests/Roomle/PartTest.php index 7158eca..1c0db04 100644 --- a/tests/Roomle/PartTest.php +++ b/tests/Roomle/PartTest.php @@ -54,18 +54,18 @@ public function testParameters() $part = new Part([ 'parameters' => [ [ - 'key' => 'height', - 'label' => 'Height', - 'type' => 'Decimal', - 'unitType' => 'length', - 'value' => '123.0' + 'key' => 'height', + 'label' => 'Height', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '123.0' ], [ - 'key' => 'width', - 'label' => 'Width', - 'type' => 'Decimal', - 'unitType' => 'length', - 'value' => '456.0' + 'key' => 'width', + 'label' => 'Width', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '456.0' ] ] ]); @@ -114,6 +114,71 @@ public function testParameters_Invalid2() $part->parameters(); } + /** + * @covers ::size + */ + public function testSize() + { + $configuration = new Part([ + 'parameters' => [ + [ + 'key' => 'depth', + 'label' => 'Depth', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '123.0' + ], + [ + 'key' => 'height', + 'label' => 'Height', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '456.0' + ], + [ + 'key' => 'width', + 'label' => 'Width', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '789.0' + ] + ] + ]); + + $this->assertSame('W 78.9 cm / H 45.6 cm / D 12.3 cm', (string)$configuration->size()); + $this->assertSame('78.9 cm', $configuration->size()->widthLabel()); + } + + /** + * @covers ::size + */ + public function testSize_Invalid() + { + $this->expectException('Kirby\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid width value'); + + $part = new Part([ + 'parameters' => [ + [ + 'key' => 'depth', + 'label' => 'Depth', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '123.0' + ], + [ + 'key' => 'height', + 'label' => 'Height', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '456.0' + ] + ] + ]); + + $part->size(); + } + /** * @covers ::__toString */ @@ -126,18 +191,18 @@ public function testToString() 'label' => 'Some part', 'parameters' => [ [ - 'key' => 'height', - 'label' => 'Height', - 'type' => 'Decimal', - 'unitType' => 'length', - 'value' => '123.0' + 'key' => 'height', + 'label' => 'Height', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '123.0' ], [ - 'key' => 'width', - 'label' => 'Width', - 'type' => 'Decimal', - 'unitType' => 'length', - 'value' => '456.0' + 'key' => 'width', + 'label' => 'Width', + 'type' => 'Decimal', + 'unitType' => 'length', + 'value' => '456.0' ] ] ]); diff --git a/tests/Roomle/SizeTest.php b/tests/Roomle/SizeTest.php new file mode 100644 index 0000000..b87dd8a --- /dev/null +++ b/tests/Roomle/SizeTest.php @@ -0,0 +1,63 @@ +assertSame('0.1 cm', Size::formatLength(1)); + $this->assertSame('1 cm', Size::formatLength(10)); + $this->assertSame('1.3 cm', Size::formatLength(13)); + $this->assertSame('123.4 cm', Size::formatLength(1234)); + $this->assertSame('1,234.5 cm', Size::formatLength(12345)); + } + + /** + * @covers ::depthLabel + * @covers ::heightLabel + * @covers ::widthLabel + */ + public function testLabels() + { + $size = new Size([ + 'depth' => 12345, + 'height' => 34567, + 'width' => 56789 + ]); + + $this->assertSame('1,234.5 cm', $size->depthLabel()); + $this->assertSame('3,456.7 cm', $size->heightLabel()); + $this->assertSame('5,678.9 cm', $size->widthLabel()); + } + + /** + * @covers ::__toString + */ + public function testToString() + { + $size = new Size([ + 'depth' => 12345, + 'height' => 34567, + 'width' => 56789 + ]); + + $this->assertSame('W 5,678.9 cm / H 3,456.7 cm / D 1,234.5 cm', (string)$size); + } +}