diff --git a/src/Modifiers/CoreModifiers.php b/src/Modifiers/CoreModifiers.php index 680ddae6a2..295e6d1264 100644 --- a/src/Modifiers/CoreModifiers.php +++ b/src/Modifiers/CoreModifiers.php @@ -157,6 +157,48 @@ public function at($value, $params) return Stringy::at($value, Arr::get($params, 0)); } + /** + * Returns an attribute ($params[0]) with its value when the given $value variable is not empty. + * + * @param string $value + * @param array $params + * @return string + */ + public function attribute($value, $params) + { + if (! $name = Arr::get($params, 0)) { + throw new \Exception('Attribute name is required.'); + } + + if ($value instanceof Collection) { + $value = $value->all(); + } + + if (\is_array($value)) { + if (empty($value)) { + return ''; + } + + $value = \json_encode($value); + } + + if (\is_bool($value)) { + return $value ? ' '.$name : ''; + } + + if (\is_object($value)) { + $value = (string) $value; + } + + $value = trim($value); + + if ($value === '') { + return ''; + } + + return sprintf(' %s="%s"', $name, Html::entities($value)); + } + /** * Returns a focal point as a background-position CSS value. * diff --git a/tests/Modifiers/AttributeTest.php b/tests/Modifiers/AttributeTest.php new file mode 100644 index 0000000000..36e3f7d3cf --- /dev/null +++ b/tests/Modifiers/AttributeTest.php @@ -0,0 +1,74 @@ +assertEquals($expected, $this->modify($value, 'foo')); + } + + public static function attributeProvider() + { + return [ + 'string' => ['bar baz', ' foo="bar baz"'], + 'entities' => ['{}', ' foo="{<!&>}"'], + 'integer' => [1, ' foo="1"'], + 'integer > 1' => [2, ' foo="2"'], + 'negative integer' => [-1, ' foo="-1"'], + 'float' => [1.5, ' foo="1.5"'], + 'empty string' => ['', ''], + 'true' => [true, ' foo'], + 'false' => [false, ''], + 'array' => [['one' => ['two' => 'three']], ' foo="{"one":{"two":"three"}}"'], + 'empty array' => [[], ''], + 'collection' => [collect(['one' => 'two']), ' foo="{"one":"two"}"'], + 'empty collection' => [collect(), ''], + 'object with __toString' => [new AttributeTestStringable, ' foo="Test"'], + ]; + } + + /** @test */ + public function it_throws_exception_without_argument() + { + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Attribute name is required.'); + + $this->modify('value', null); + } + + /** @test */ + public function it_throws_exception_when_value_is_an_object_without_toString_method() + { + $this->expectException(\Error::class); + $this->expectExceptionMessage('Object of class Tests\Modifiers\AttributeTestNotStringable could not be converted to string'); + + $this->modify(new AttributeTestNotStringable, 'foo'); + } + + private function modify($value, $attribute) + { + return Modify::value($value)->attribute($attribute)->fetch(); + } +} + +class AttributeTestStringable +{ + public function __toString() + { + return 'Test'; + } +} + +class AttributeTestNotStringable +{ +}