Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.x] Attribute Modifier #9796

Merged
merged 14 commits into from
May 21, 2024
42 changes: 42 additions & 0 deletions src/Modifiers/CoreModifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
74 changes: 74 additions & 0 deletions tests/Modifiers/AttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Tests\Modifiers;

use Statamic\Modifiers\Modify;
use Tests\TestCase;

class AttributeTest extends TestCase
{
/**
* @test
*
* @dataProvider attributeProvider
*/
public function it_converts_to_attribute($value, $expected)
{
$this->assertEquals($expected, $this->modify($value, 'foo'));
}

public static function attributeProvider()
{
return [
'string' => ['bar baz', ' foo="bar baz"'],
'entities' => ['{<!&>}', ' foo="{&lt;!&amp;&gt;}"'],
'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="{&quot;one&quot;:{&quot;two&quot;:&quot;three&quot;}}"'],
'empty array' => [[], ''],
'collection' => [collect(['one' => 'two']), ' foo="{&quot;one&quot;:&quot;two&quot;}"'],
'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(\Exception::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
{
}
Loading