diff --git a/src/Entity/Attachments/Attachment.php b/src/Entity/Attachments/Attachment.php index 81e0ea23..0310f7db 100644 --- a/src/Entity/Attachments/Attachment.php +++ b/src/Entity/Attachments/Attachment.php @@ -103,10 +103,9 @@ abstract class Attachment extends NamedDBElement */ public function isExternal() : bool { - //return static::isUrl($this->getPath()); //Treat all pathes without a filepath as external - return (strpos($this->getPath(), '%MEDIA%') === false) - && (strpos($this->getPath(), '%BASE') === false); + return (strpos($this->getPath(), '%MEDIA%') !== 0) + && (strpos($this->getPath(), '%BASE%') !== 0); } /******************************************************************************** @@ -118,11 +117,15 @@ abstract class Attachment extends NamedDBElement /** * Returns the extension of the file referenced via the attachment. * For a path like %BASE/path/foo.bar, bar will be returned. - * @return string + * If this attachment is external null is returned. + * @return string|null The file extension in lower case. */ - public function getExtension() : string + public function getExtension() : ?string { - return pathinfo($this->getPath(), PATHINFO_EXTENSION); + if ($this->isExternal()) { + return null; + } + return strtolower(pathinfo($this->getPath(), PATHINFO_EXTENSION)); } /** diff --git a/src/Services/AmountFormatter.php b/src/Services/AmountFormatter.php index 0265b3bd..224809b2 100644 --- a/src/Services/AmountFormatter.php +++ b/src/Services/AmountFormatter.php @@ -124,7 +124,11 @@ class AmountFormatter } //Otherwise just output it - $format_string = '%.' . $options['decimals'] . 'f ' . $options['unit']; + if (!empty($options['unit'])) { + $format_string = '%.' . $options['decimals'] . 'f ' . $options['unit']; + } else { //Dont add space after number if no unit was specified + $format_string = '%.' . $options['decimals'] . 'f'; + } return sprintf($format_string, $value); } } \ No newline at end of file diff --git a/src/Services/SIFormatter.php b/src/Services/SIFormatter.php index 083d3cb4..06d8ee20 100644 --- a/src/Services/SIFormatter.php +++ b/src/Services/SIFormatter.php @@ -58,12 +58,11 @@ class SIFormatter $prefixes_pos = ['' ,'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; $prefixes_neg = ['' ,'m', 'μ', 'n', 'p', 'f', 'a', 'z', 'y']; - //Determine nearest prefix index. - $nearest = (int) round(abs($magnitude) / 3); - if ($magnitude >= 0) { + $nearest = (int) floor(abs($magnitude) / 3); $symbol = $prefixes_pos[$nearest]; } else { + $nearest = (int) round(abs($magnitude) / 3); $symbol = $prefixes_neg[$nearest]; } @@ -105,7 +104,11 @@ class SIFormatter [$divisor, $symbol] = $this->getPrefixByMagnitude($this->getMagnitude($value)); $value /= $divisor; //Build the format string, e.g.: %.2d km - $format_string = '%.' . $decimals . 'f ' . $symbol . $unit; + if ($unit !== '' || $symbol !== '') { + $format_string = '%.' . $decimals . 'f ' . $symbol . $unit; + } else { + $format_string = '%.' . $decimals . 'f'; + } return sprintf($format_string, $value); } diff --git a/tests/Entity/AttachmentTest.php b/tests/Entity/AttachmentTest.php new file mode 100644 index 00000000..974be68b --- /dev/null +++ b/tests/Entity/AttachmentTest.php @@ -0,0 +1,147 @@ +setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.txt'); + $this->assertFalse($attachment->isExternal()); + + $this->setProtectedProperty($attachment, 'path', '%BASE%/foo/bar.jpg'); + $this->assertFalse($attachment->isExternal()); + + //Every other string is not a external attachment + $this->setProtectedProperty($attachment, 'path', '%test%/foo/bar.ghp'); + $this->assertTrue($attachment->isExternal()); + + $this->setProtectedProperty($attachment, 'path', 'foo%MEDIA%/foo.jpg'); + $this->assertTrue($attachment->isExternal()); + + $this->setProtectedProperty($attachment, 'path', 'foo%MEDIA%/%BASE%foo.jpg'); + $this->assertTrue($attachment->isExternal()); + } + + public function testGetExtension() + { + $attachment = new PartAttachment(); + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.txt'); + $this->assertEquals('txt', $attachment->getExtension()); + + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.JPeg'); + $this->assertEquals('jpeg', $attachment->getExtension()); + + $this->setProtectedProperty($attachment, 'path', 'https://foo.bar'); + $this->assertNull( $attachment->getExtension()); + + $this->setProtectedProperty($attachment, 'path', 'https://foo.bar/test.jpeg'); + $this->assertNull( $attachment->getExtension()); + } + + public function testIsPicture() + { + $attachment = new PartAttachment(); + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.txt'); + $this->assertFalse($attachment->isPicture()); + + $this->setProtectedProperty($attachment, 'path', 'https://test.de/picture.jpeg'); + $this->assertTrue($attachment->isPicture()); + + $this->setProtectedProperty($attachment, 'path', 'https://test.de'); + $this->assertTrue($attachment->isPicture()); + + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.jpeg'); + $this->assertTrue($attachment->isPicture()); + + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.webp'); + $this->assertTrue($attachment->isPicture()); + } + + public function testGetHost() + { + $attachment = new PartAttachment(); + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.txt'); + $this->assertNull($attachment->getHost()); + + $this->setProtectedProperty($attachment, 'path', 'https://www.google.de/test.txt'); + $this->assertEquals('www.google.de', $attachment->getHost()); + } + + public function testGetFilename() + { + $attachment = new PartAttachment(); + $this->setProtectedProperty($attachment, 'path', '%MEDIA%/foo/bar.txt'); + $this->assertEquals('bar.txt', $attachment->getFilename()); + + $this->setProtectedProperty($attachment, 'path', 'https://www.google.de/test.txt'); + $this->assertNull($attachment->getFilename()); + } + + public function testIsURL() + { + $url = '%MEDIA%/test.txt'; + $this->assertFalse(Attachment::isURL($url)); + + $url = 'https://google.de'; + $this->assertFalse(Attachment::isURL($url)); + + $url = 'ftp://google.de'; + $this->assertTrue(Attachment::isURL($url, false, false)); + $this->assertFalse(Attachment::isURL($url, false, true)); + } + + /** + * Sets a protected property on a given object via reflection + * + * @param object $object - instance in which protected value is being modified + * @param string $property - property on instance being modified + * @param mixed $value - new value of the property being modified + * + * @return void + */ + public function setProtectedProperty($object, $property, $value) + { + $reflection = new ReflectionClass($object); + $reflection_property = $reflection->getProperty($property); + $reflection_property->setAccessible(true); + $reflection_property->setValue($object, $value); + } + +} \ No newline at end of file diff --git a/tests/Entity/PartInstockTest.php b/tests/Entity/PartInstockTest.php new file mode 100644 index 00000000..f4fa30ab --- /dev/null +++ b/tests/Entity/PartInstockTest.php @@ -0,0 +1,110 @@ +float_unit = new MeasurementUnit(); + $this->float_unit->setIsInteger(false); + $this->int_unit = new MeasurementUnit(); + $this->int_unit->setIsInteger(true); + } + + public function testUseFloatAmount() + { + $part = new Part(); + $part->setPartUnit(null); + $this->assertFalse($part->useFloatAmount()); + + $part->setPartUnit($this->float_unit); + $this->assertTrue($part->useFloatAmount()); + + $part->setPartUnit($this->int_unit); + $this->assertFalse($part->useFloatAmount()); + } + + public function testGetMinAmount() + { + $part = new Part(); + $part->setMinAmount(10.32); + $part->setPartUnit(null); + $this->assertEquals(10.0, $part->getMinAmount()); + + $part->setPartUnit($this->float_unit); + $this->assertEquals(10.32, $part->getMinAmount()); + } + + public function testAddPartLot() + { + $part = new Part(); + //Part must be empty after creation + $this->assertEmpty($part->getPartLots()); + $part_lot = new PartLot(); + $part->addPartLot($part_lot); + + $this->assertCount(1, $part->getPartLots()); + //PartLot must now be assigned to part + $this->assertEquals($part, $part_lot->getPart()); + } + + public function testGetAmountSum() + { + $part = new Part(); + $part->addPartLot((new PartLot())->setAmount(5.42)); + $part->addPartLot((new PartLot())->setAmount(0.4)); + $part->addPartLot((new PartLot())->setAmount(10.4)); + $part->addPartLot((new PartLot())->setAmount(100)->setInstockUnknown(true)); + + $part->setPartUnit(null); + //It is important that we get 15 here (values are round and then summed), not 16 (sum and then round) + $this->assertEquals(15, $part->getAmountSum()); + + $part->setPartUnit($this->float_unit); + $this->assertEquals(16.22, $part->getAmountSum()); + } +} \ No newline at end of file diff --git a/tests/Entity/StructuralDBElementTest.php b/tests/Entity/StructuralDBElementTest.php new file mode 100644 index 00000000..3ed0717f --- /dev/null +++ b/tests/Entity/StructuralDBElementTest.php @@ -0,0 +1,132 @@ +root = new AttachmentType(); + $this->root->setName('root')->setParent(null); + $this->child1 = new AttachmentType(); + $this->child1->setParent($this->root)->setName('child1'); + $this->child2 = new AttachmentType(); + $this->child2->setName('child2')->setParent($this->root); + $this->child3 = new AttachmentType(); + $this->child3->setName('child3')->setParent($this->root); + $this->child1_1 = new AttachmentType(); + $this->child1_1->setName('child1_1')->setParent($this->child1); + $this->child1_2 = new AttachmentType(); + $this->child1_2->setName('child1_2')->setParent($this->child1); + } + + public function testIsRoot() + { + $this->assertTrue($this->root->isRoot()); + $this->assertFalse($this->child1->isRoot()); + $this->assertFalse($this->child1_2->isRoot()); + } + + public function testIsChildOf() + { + //Root must not be the child of any other node + $this->assertFalse($this->root->isChildOf($this->child1)); + $this->assertFalse($this->root->isChildOf($this->root)); + + //Check for direct parents + $this->assertTrue($this->child1->isChildOf($this->root)); + $this->assertTrue($this->child1_2->isChildOf($this->child1)); + + //Check for inheritance + $this->assertTrue($this->child1_2->isChildOf($this->root)); + } + + public function testChildOfDifferentClasses() + { + $this->expectException(\InvalidArgumentException::class); + $category = new Category(); + $this->root->isChildOf($category); + } + + public function testChildOfExtendedClass() + { + //Doctrine extends the entities for proxy classes so the isChildOf mus also work for inheritance types + $inheritance = new class extends AttachmentType {}; + $inheritance->setParent($this->root); + $this->assertTrue($inheritance->isChildOf($this->root)); + $this->assertFalse($this->root->isChildOf($inheritance)); + } + + public function testGetLevel() + { + $this->assertEquals(0, $this->root->getLevel()); + $this->assertEquals(1, $this->child1->getLevel()); + $this->assertSame(1, $this->child2->getLevel()); + $this->assertSame(2, $this->child1_2->getLevel()); + $this->assertSame(2, $this->child1_1->getLevel()); + } + + public function testGetFullPath() + { + $this->assertSame('root/child1/child1_1', $this->child1_1->getFullPath('/')); + $this->assertSame('root#child2', $this->child2->getFullPath('#')); + } + + public function testGetPathArray() + { + $this->assertEquals([$this->root, $this->child1, $this->child1_1], $this->child1_1->getPathArray()); + $this->assertEquals([$this->root, $this->child1], $this->child1->getPathArray()); + $this->assertEquals([$this->root], $this->root->getPathArray()); + } + +} \ No newline at end of file diff --git a/tests/Services/AmountFormatterTest.php b/tests/Services/AmountFormatterTest.php new file mode 100644 index 00000000..8829774c --- /dev/null +++ b/tests/Services/AmountFormatterTest.php @@ -0,0 +1,108 @@ +service = self::$container->get(AmountFormatter::class); + } + + public function testFormatWithoutUnit() + { + $this->assertEquals("2", $this->service->format(2.321)); + $this->assertEquals("1002", $this->service->format(1002.356)); + $this->assertEquals("1000454", $this->service->format(1000454.0)); + $this->assertEquals("0", $this->service->format(0.01)); + $this->assertEquals("0", $this->service->format(0)); + } + + public function testInvalidInput() + { + $this->expectException(\InvalidArgumentException::class); + $this->service->format("test"); + } + + public function testFormatUnitWithoutSI() + { + $meters = new MeasurementUnit(); + $meters->setIsInteger(false)->setUseSIPrefix(false)->setUnit("m"); + + $this->assertEquals('0.32 m', $this->service->format(0.3245, $meters)); + $this->assertEquals('10003.56 m', $this->service->format(10003.556, $meters)); + $this->assertEquals('0.00 m', $this->service->format(0.0004, $meters)); + } + + public function testFormatUnitWithSI() + { + $meters = new MeasurementUnit(); + $meters->setIsInteger(false)->setUseSIPrefix(true)->setUnit('m'); + + $this->assertEquals('0.32 m', $this->service->format(0.3245, $meters)); + $this->assertEquals('12.32 m', $this->service->format(12.323, $meters)); + $this->assertEquals('120.32 km', $this->service->format(120320.45, $meters)); + + $this->assertEquals('0.32 mm', $this->service->format(0.00032, $meters)); + } + + public function testFormatMoreDigits() + { + $this->assertEquals('12.12345', $this->service->format(12.1234532, null, ['is_integer' => false, 'decimals' => 5])); + $this->assertEquals('12.1', $this->service->format(12.1234532, null, ['is_integer' => false, 'decimals' => 1])); + } + + public function testFormatOptionsOverride() + { + $meters = new MeasurementUnit(); + $meters->setIsInteger(false)->setUseSIPrefix(true)->setUnit('m'); + + $this->assertEquals('12.32', $this->service->format(12.323, $meters, ['unit' => ''])); + $this->assertEquals('12002.32 m', $this->service->format(12002.32, $meters, ['show_prefix' => false])); + $this->assertEquals('123 m', $this->service->format(123.234, $meters, ['is_integer' => true])); + } +} \ No newline at end of file diff --git a/tests/Services/SIFormatterTest.php b/tests/Services/SIFormatterTest.php index 405b68e1..0e78e9df 100644 --- a/tests/Services/SIFormatterTest.php +++ b/tests/Services/SIFormatterTest.php @@ -74,9 +74,11 @@ class SIFormatterTest extends WebTestCase public function testgetPrefixByMagnitude() { + $this->assertSame([1, ''], $this->service->getPrefixByMagnitude(2)); + $this->assertSame([1000, 'k'], $this->service->getPrefixByMagnitude(3)); - $this->assertSame([1000, 'k'], $this->service->getPrefixByMagnitude(2)); $this->assertSame([1000, 'k'], $this->service->getPrefixByMagnitude(4)); + $this->assertSame([1000, 'k'], $this->service->getPrefixByMagnitude(5)); $this->assertSame([0.001, 'm'], $this->service->getPrefixByMagnitude(-3)); $this->assertSame([0.001, 'm'], $this->service->getPrefixByMagnitude(-2)); @@ -86,6 +88,8 @@ class SIFormatterTest extends WebTestCase public function testFormat() { $this->assertSame("2.32 km", $this->service->format(2321, 'm')); + $this->assertEquals("230.45 km", $this->service->format(230450.3, 'm')); $this->assertSame("-98.20 mg", $this->service->format(-0.0982, 'g')); + $this->assertSame('-0.23 g', $this->service->format(-0.23, 'g')); } } \ No newline at end of file